37 votes

Pourquoi ces deux opérations de multiplication donnent-elles des résultats différents?

Pourquoi dois-je ajouter une lettre "L" pour obtenir la valeur longue correcte? Et quelle est l'autre valeur?

 long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;
System.out.println(oneYearWithL);//gives correct calculation result : 31536000000
System.out.println(oneYearWithoutL)//gives incorrect calculation result: 1471228928
 

133voto

Rohit Jain Points 90368
long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;

Votre première valeur est en fait une longue (Depuis 365L est long, et 1000*60*60*24 est integer, de sorte que le résultat de l' multiplying un long de la valeur avec un integer de la valeur est une long de la valeur.

Mais la 2ème valeur est un entier (Puisque vous êtes mulitplying un integer de la valeur avec un integer de la valeur seulement. Donc, le résultat sera un 32-bit entier. Maintenant, le résultat obtenu pour qui multiplication est en dehors de la portée réelle de l'entier. Donc, avant d'être affecté à la variable, il est tronqué en entier valide gamme.

Jetez un oeil à l'instruction print: -

System.out.println(1000*60*60*24*365L);
System.out.println(1000*60*60*24*365);
System.out.println(Integer.MAX_VALUE);

Lorsque vous exécutez le code ci-dessus: -

Sortie: -

31536000000
1471228928
2147483647

Donc, vous pouvez voir la différence..

011101010111101100010010110000000000 -- Binary equivalent of 1000*60*60*24*365L
    01111111111111111111111111111111 -- Binary equivalent of Integer.MAX_VALUE

Donc, si vous n'ajoutez pas qu' L à la fin de votre numéro, le 4 bit de poids fort est retiré de la première chaîne binaire..

Ainsi, la chaîne devient..

(0111)01010111101100010010110000000000 -- Remove the most significant bits..
      01010111101100010010110000000000 -- Binary equivalent of 1471228928

(que vous obtiendrez en sortie)


Mise à JOUR: - À partir de l'explication ci-dessus, vous pouvez aussi comprendre que, même dans la première affectation, si le résultat de votre multiplication de integers avant de multiplier il avec 365L sort de la plage, puis à nouveau, il sera tronqué dans l'intervalle entier, ou convertis en 2's complement representation , si nécessaire, et ensuite seulement il sera multiplié par l' long value - 365L.

Pour l'e.g: -

long thirtyYearWithL = 1000*60*60*24*30*365L;

Dans l'exemple ci-dessus, l'examen de la première partie - 1000*60*60*24*30. Le résultat de cette multiplication est: - 2592000000. Maintenant, permet de' voir comment il est représenté en binary equivalent: -

2592000000 = 10011010011111101100100000000000  -- MSB is `1`, a negative value
             01100101100000010011100000000001  -- 2's complement representation

Représentation décimale de l' 2's complement représentation est - 1702967297. Donc, 2592000000 est converti -1702967297, avant de se multiplier pour 365L. Depuis, cette valeur s'inscrit dans l' integer range qui est : - [-2147483648 to 2147483647], de sorte qu'il ne sera pas tronqué plus loin.

Donc, le résultat sera: -

long thirtyYearWithL = 1000*60*60*24*30*365L;
                     = 2592000000 * 365L;
                     = -1702967297 * 365L = -621583063040

Donc, tous ces étoffes juste estime le réel type du résultat final sur l'application de l'opération arithmétique. Et ce contrôle est effectué sur chaque temporaire du résultat des opérations de déménagement à partir de left to right(en tenant compte d'opérateurs left-to-right associativité). Si aucun résultat temporaire est trouvé pour être hors de portée, puis converti en conséquence pour tenir dans la plage requise, avant d'aller de l'avant avec l'opération suivante.


Mise à JOUR 2: -

Ainsi, au lieu de: -

long thirtyYearWithL = 1000*60*60*24*30*365L;

si vous déplacez votre 365L au début, puis vous obtiendrez le résultat correct: -

long thirtyYearWithL = 365L*1000*60*60*24*30; // will give you correct result

Parce que, maintenant, votre temporary résultat sera de type long, et est capable de retenir cette valeur.

15voto

Steven McGrath Points 1147

Sans le " L " de votre calcul est réalisé comme une valeur de 32 bits. Si on exprime les valeurs hexadécimales, la plus petite valeur est la plus faible de 4 octets de la valeur la plus grande.

Java par défaut pour les 32 bits de type entier. Le "L", pour Longtemps, est de 64 bits. En mettant L après 365, vous dire au compilateur de traiter 365 comme une valeur de type long. Lors de la 32 bits et 64 bits des valeurs sont multipliées, le compilateur upcasts la valeur 32 bits à 64 bits, de sorte que les résultats intermédiaires de l'évaluation de votre expression de garder la totalité de 64 bits de large.

Voir les Types Primitifs et les Valeurs dans la Spécification du Langage Java http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#85587 .

Le comportement de la multiplication est définie explicitement à http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#239829 comme suit:

15.17.1 Opérateur De Multiplication *

Le binaire * opérateur effectue la multiplication, la production du produit de ses opérandes. La Multiplication est une opération commutative si l' opérande expressions ont pas d'effets secondaires. Tout entier multiplication est associative lorsque les opérandes sont de même type, multiplication en virgule flottante n'est pas associatif. Si un nombre entier la multiplication des débordements, alors le résultat est le faible de bits d'ordre de la produit mathématique représentée dans certaines suffisamment grand en complément à deux sur format. En conséquence, si le dépassement se produit, alors la signe du résultat peut ne pas être le même que le signe de la mathématique produit de deux opérande valeurs.

Le résultat d'une multiplication en virgule flottante est régi par les règles de la norme IEEE 754 arithmétique:

Si l'un des deux opérandes est NaN, le résultat est NaN. Si le résultat n'est pas NaN, le signe du résultat est positif si les deux opérandes ont la même signe, et négatif si les opérandes ont des signes différents. La Multiplication d'un infini par un zéro renvoie NaN. La Multiplication d'un infini par une valeur finie résultats dans un signé l'infini. L' signe est déterminé par la règle énoncée ci-dessus. Dans les autres cas, où ni infini, ni NaN, la mathématique exacte le produit est calculée. Une valeur à virgule flottante est ensuite choisi: Si l' la multiplication expression est FP-strict (§15.4): Si le type de la la multiplication expression est float, alors la valeur flottante doit être choisi. Si le type de la multiplication expression est double, alors le double de la valeur doit être choisie. Si la multiplication expression n'est pas FP-strict: Si le type de la multiplication expression est flotteur, le flotteur de la valeur définie ou le float-extended-exposant définir la valeur peut être choisie, en fonction de l'humeur de la mise en œuvre. Si l' type de la multiplication expression est double, soit la double de la valeur réglée ou les double-étendue-valeur d'exposant l'ensemble peut être choisi, au gré de la mise en œuvre. Ensuite, une valeur doit être choisi à partir de la valeur choisie à représenter le produit. Si l' l'ampleur du produit est trop grand pour représenter l'on dit que le fonctionnement des débordements; le résultat est alors une infinité de appropriée signe. Sinon, le résultat est arrondi à la valeur la plus proche dans le choisi la valeur définie à l'aide de la norme IEEE 754 arrondi au plus proche de mode. La Java langage de programmation nécessite la prise en charge progressive de l'underflow tel que défini par la norme IEEE 754 (§4.2.4).

Malgré le fait que dépassement de, dépassement de capacité, ou de perte d'information peut se produire, l'évaluation d'un opérateur de multiplication * ne jamais jette un au moment de l'exécution d'exception.

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