39 votes

Comment la conversion de type entier se comporte-t-elle en Java pour les nombres au-delà de la plage des nombres entiers?

Voici mon programme.

 public class Foo
{
    public static void main(String[] args)
    {
        System.out.println((int) 2147483648l);
        System.out.println((int) 2147483648f);
    }
}
 

Voici la sortie.

 -2147483648
2147483647
 

Pourquoi les types 2147483648l et 2147483648f convertis au même nombre entier? Pouvez-vous expliquer ce qui se passe ici ou quel concept en Java je dois comprendre pour prédire la sortie de transtypages comme ceux-ci?

75voto

T.J. Crowder Points 285826

Ces exemples illustrent le Rétrécissement Primitives de Conversion de l'opération.

Dans ton premier exemple, long de int:

Un rétrécissement de la conversion d'un entier signé intégrante de type T supprime simplement les tous, mais le n le plus bas de l'ordre de bits, où n est le nombre de bits utilisés pour représenter le type de T. En plus d'une possible perte d'information sur l'ampleur de la valeur numérique, cela peut entraîner le signe de la valeur obtenue à différer le signe de la valeur d'entrée.

Si votre (int) 2147483648l est de prendre la version 64 bits de l' long:

00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000

...et laisser tomber le top 32 bits entièrement:

10000000 00000000 00000000 00000000

...et de prendre le reste en 32 bits comme un int. Depuis la plus à gauche de celles-ci est maintenant un bit de signe (long et int sont stockés en tant que complément à deux), et depuis, il arrive à être mis dans votre 2147483648l de la valeur, vous vous retrouvez avec un nombre négatif. Depuis pas d'autres bits sont définis, en complément à deux, cela signifie que vous avez le plus faible nombre négatif int peut représenter: -2147483648.

L' float de int exemple suit une règle plus complexe. Les parties pertinentes de votre valeur sont les suivants:

...si le nombre à virgule flottante n'est pas l'infini, la valeur à virgule flottante est arrondi à un nombre entier de valeur V, arrondi vers zéro à l'aide de la norme IEEE 754 aller-vers-le mode de zéro (§4.2.3).

...[si] la valeur [est] trop grand (une valeur positive de grande ampleur ou de l'infini positif), [puis] le résultat de la première étape est la plus grande valeur représentable de type int ou long.

(Mais voir la partie de la spécification ci-dessus pour les détails.)

Donc, depuis 2147483648f rondes 2147483648, et 2147483648 est trop grand pour tenir dans int, la plus grande valeur pour l' int (2147483647) est utilisé à la place.

Ainsi, dans l' long de int, c'est peu tripoter; dans l' float de int, c'est plus mathématique.


Dans un commentaire vous avez demandé:

Savez-vous pourquoi les deux (short) 32768 et (short) 32768f évaluer à l' -32768? J'ai été exepecting ce dernier afin d'évaluer la 32767.

Excellente question, et c'est là que mon "voir la partie de la spécification ci-dessus pour les détails" ci-dessus vient en. :-) (short) 32768f n'est, en effet, (short)(int)32768f:

Dans la spécification de l'article lié ci-dessus, sous "Un rétrécissement de la conversion d'un nombre à virgule flottante intégrante de type T effectue en deux étapes:", dit-il

  1. Dans la première étape, le nombre à virgule flottante est converti à un long, si T est - long, ou à un int, si T est - byte, short, charou int...

et puis plus tard dans l'Étape 2 de la deuxième puce:

  1. * Si T est - byte, charou short, le résultat de la conversion est le résultat d'un rétrécissement de conversion de type T (§5.1.3) du résultat de la première étape.

Ainsi, dans la première étape, 32768f devient 32768 (un int de la valeur), et puis, bien sûr, (short)32768 ne le bit-hacher nous l'avons vu dans long => int - dessus, nous donnant un short de la valeur de -32768.

20voto

Bathsheba Points 23209

Nice! C'est merveilleux de voir les effets des décisions de conception présenté dans la façon que vous avez.

2147483648l est long type et la règle de conversion d'un long c'est trop gros pour l' int est à appliquer le wrap-around règle dans le type de destination. (Sous le capot, le nombre de bits significatifs à partir du type de source sont tout simplement jetés.)

2147483648f est float type et la règle de conversion d'un float qui est trop gros pour le type de destination est de prendre le plus grand possible pour le type de destination. Référence de Java de type entier primitif jette "plafonné" à la MAX_INT de la coulée type?

La bonne chose à propos des normes est qu'il ya tellement beaucoup à choisir de.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X