Question

Pourquoi ce code java

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

Lors de l'exécution, sortie

1
1
107374182400
0

au lieu de l'attendu

1
1
107374182400
107374182400

production?

Était-ce utile?

La solution 2

107374182400 est exactement 25 fois la gamme complète d'un entier (2 ^ 32), ce qui signifie que si vous essayez de l'intégrer dans un entier, il va débordement. Et parce que cela s'adapterait exactement 25 fois, il se termine précisément sur 0 (c'est une coïncidence et d'autres multiplications énormes peuvent finir par être positive ou négative). Et vous utilisez un entier jusqu'au point que vous jetez à Long

long a1 = 100 * 1024 * 1024 * 1024;

est équivalent à

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

Si vous mettez un seul long dans l'expression, il est obligé d'utiliser de longs mathématiques et non des mathématiques entiers qui suppriment le problème

Autres conseils

 long a2 = 100L * 1024 * 1024 * 1024;

Dans cette opération cependant, au moins un opérande est long. Par conséquent, l'opération est effectuée en utilisant une précision 64 bits, et le résultat de l'opérateur numérique est de type long. Les autres opérands non longs sont élargis pour type long par Promotion numérique et la valeur résultante est stockée à la variable a2.

 long a1 = 100 * 1024 * 1024 * 1024;

L'expression constante d'un entier simple, le résultat de l'expression a été calculé comme un type int. La valeur calculée, cependant, trop grande pour s'adapter dans un entier et donc débordé, ce qui a entraîné 0 et est stocké pour a1 variable.

Edit: comme on le demande dans le commentaire suivant:

Pourquoi ça ne va pas négatif?

Parce que dans calcul entier Le deuxième calcul équivaut à 25 * 2^32^ a le sens du pouvoir et 2^32 La valeur entière est 0. Cependant, pour expliquer pourquoi sa valeur est 0: En binaire:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31 est un entier négatif (-2147483648) Comme le bit du signe est 1 Et donc 2 ^ 32 est juste une multiplication de 2 à 2 ^ 31: un changement de gauche et le bit de signe deviendra 0 Et donc le résultat est 0.

Vérifiez java language specification: 4.2.2: Integer operation pour plus de détails.

Il se peut que l'expression à droite de a1 est d'abord calculé comme un int et plus tard converti en long. Si cela équivaut 0 en tant que int ça restera 0 comme un long

Selon le Documentation des littéraux lexicaux il est mentionné que,

Le type de littéral est déterminé comme suit:
- Le type d'un littéral entier (§3.10.1) qui se termine par L ou L est long (§4.2.1).
- Le type de tout autre littéral entier est int (§4.2.1).

Ainsi votre expression, 100 * 1024 * 1024 * 1024 est évalué comme int Type de données primitives car l ou L n'est mentionné dans aucune valeur numérique. Et le résultat est 107374182400 c'est-à-dire en binaire c'est 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 et int est 32 bits si bas 32 bits sont pris comme mentionné dans Exemple 4.2.2-1. Opérations entières qui résulte de 0

Il est également mentionné dans la même documentation que,

Si un opérateur entier autre qu'un opérateur de décalage a au moins un opérande de type long, l'opération est effectuée en utilisant une précision 64 bits et le résultat de l'opérateur numérique est de type long. Si l'autre opérande n'est pas long, il est d'abord élargi (§5.1.5) pour taper longtemps par promotion numérique

Cela signifie que toute valeur d'expression contient l ou L alors tous les int Les valeurs seront étendues à 64 bits.

ÉDITER Dans le commentaire On lui demande également

Pourquoi ça ne va pas négatif?

Je pense que c'est aussi répond à la question ci-dessus

long a4 = 1L; // Pas de problème à ce sujet

long a3 = 1; // Ici, le côté gauche primitif est considéré comme entier et au moment de l'attribution, il sera jeté longtemps, donc encore un résultat est comme prévu

long a2 = 100L * 1024 * 1024 * 1024; (Ici, vous avez utilisé 100L pour que d'autres soient conduits à la sortie longtemps donc à la sortie attendue)

long a1 = 100 * 1024 * 1024 * 1024; (Comme par défaut, tout chiffre primitif est considéré comme int dans Java, il le considérera comme une multiplication entière, il est donc hors de portée et entraîne 0)

Voici ce que vous avez fait: vous avez attribué 100 * 1024 * 1024 * 1024à un long type de données mais vous n'avez pas dit que 100 * 1024 * 1024 * 1024 est une longue valeur

Par défaut, le compilateur Java pense que c'est un entier. Étant donné qu'Integer ne peut pas maintenir autant de valeur, cela montrera un mauvais résultat. J'espère que cela aide !

la raison est débordement entier
comme sortie de 100 * 1024 * 1024 * 1024; est un entier (int) ne pas long

et en long a2 = 100L * 1024 * 1024 * 1024; vous spécifiez que l'une des valeurs est long (ici 100L) et la multiplication avec cette valeur entraîne long valeur qui est correctement stockée dans a2

En Java, si vous avez int * int, il calculera la sortie en tant qu'int. Cela ne donne le résultat que si vous faites int * long. Dans votre cas, le 100 * 1024 * 1024 * 1024 a un résultat qui déborde Int.

Ainsi, l'ajout d'un "L" fait que l'opérande est long, et le calcul stocke les valeurs longues. Et bien sûr, aucun débordement ne se produit et un résultat correct peut être sorti (c'est-à-dire A2).

Le numéro 3 a fonctionné car vous avez spécifié un type long qui est de 100L. C'est pourquoi c'est une longue multiplication et pourrait être stocké. D'un autre côté, le numéro 4 est une multiplication entière avec max valeur 2 ^ 32-1 C'est pourquoi vous avez un débordement et la valeur par défaut zéro est apparue.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top