Pregunta

¿Por qué este código 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);

Cuando se ejecuta, salida

1
1
107374182400
0

en lugar de lo esperado

1
1
107374182400
107374182400

¿producción?

¿Fue útil?

Solución 2

107374182400 es exactamente 25 veces el rango completo de un entero (2^32), lo que significa que si intentas colocarlo en un entero, lo hará Desbordamiento. Y debido a que encajaría exactamente 25 veces, termina precisamente en 0 (esta es una coincidencia y otras multiplicaciones enormes pueden terminar positivas o negativas). Y estás usando un entero hasta el punto que lanzarás hasta mucho tiempo

long a1 = 100 * 1024 * 1024 * 1024;

es equivalente a

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

Si pone un solo largo en la expresión, se ve obligado a usar matemáticas largas, no matemáticas enteras, lo que elimina el problema

Otros consejos

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

En esta operación, sin embargo, al menos un operando es long. Por lo tanto, la operación se lleva a cabo utilizando una precisión de 64 bits, y el resultado del operador numérico es de tipo long. El otro operando no largo se amplía al tipo long por promoción numérica y el valor resultado se almacena a la variable a2.

 long a1 = 100 * 1024 * 1024 * 1024;

La expresión constante de entero simple, el resultado de la expresión se calculó como un tipo int. El valor calculado, sin embargo, demasiado grande para caber en un entero y, por lo tanto, se desborda, lo que resulta en 0 y se almacena para a1 variable.

Editar: como se solicita en el siguiente comentario:

¿Por qué no se hace negativo?

Porque mientras estaba en cálculo entero El segundo cálculo es equivalente a 25 * 2^32 dónde ^ tiene el significado de poder y 2^32 El valor entero es 0. Sin embargo, para explicar por qué su valor es 0: En binario:

 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 es un entero negativo (-2147483648) como es el bit de signo 1 Y por lo tanto 2 ^ 32 es solo una multiplicación de 2 a 2 ^ 31: un cambio a la izquierda y el bit de signo se convertirá en 0 y de ahí el resultado es 0.

Revisar la java language specification: 4.2.2: Integer operation para detalles.

Podría ser que la expresión a la derecha de a1 se calcula primero como un int y más tarde convertido a long. Si es igual a 0 como int se quedará 0 como un long

Según el Documentación de literales léxicos se menciona que,

El tipo de literal se determina de la siguiente manera:
- El tipo de un entero literal (§3.10.1) que termina con L o L es largo (§4.2.1).
- El tipo de cualquier otro literal entero es int (§4.2.1).

Así tu expresión, 100 * 1024 * 1024 * 1024 se evalúa como int Tipo de datos primitivos porque l o L no se menciona en ningún valor numérico. y el resultado es 107374182400 es decir, en binario es 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 y int son 32 bits, por lo que se toman 32 bits bajos como se menciona en Ejemplo 4.2.2-1. Operaciones enteras que resulta a 0

También se menciona en la misma documentación que,

Si un operador entero que no sea un operador de cambio tiene al menos un operando de tipo largo, entonces la operación se lleva a cabo utilizando una precisión de 64 bits, y el resultado del operador numérico es de tipo largo. Si el otro operando no es largo, primero se amplía (§5.1.5) escribe largo por promoción numérica

Significa que cualquier valor en la expresión contiene l o L Entonces todo el int Los valores se ampliarán a 64 bits.

EDITAR En el comentario También se le pregunta

¿Por qué no se hace negativo?

Creo que también Responde a la pregunta anterior

long a4 = 1L; // No hay problema en esto

long a3 = 1; // Aquí el lado izquierdo primitivo se considera entero y en el momento de la asignación se lanzará a mucho tiempo, por lo que el resultado es como se esperaba como se esperaba

long a2 = 100L * 1024 * 1024 * 1024; (Aquí ha usado 100L para que otros sean fundidos a larga, por lo que la salida esperada)

long a1 = 100 * 1024 * 1024 * 1024; (Como por defecto, cualquier dígito primitivo se considera int en Java, considerará esto como multiplicación entera para que salga de rango y resulte en 0)

Esto es lo que hiciste: asignaste 100 * 1024 * 1024 * 1024a un tipo de datos largo pero no dijo eso 100 * 1024 * 1024 * 1024 es un valor largo

Por defecto, Java Compiler piensa que es un entero. Dado que Integer no puede tener tanto valor, mostrará un resultado incorrecto. Espero eso ayude !

La razón es desbordamiento de enteros
como salida de 100 * 1024 * 1024 * 1024; es un entero (int) no long

y en long a2 = 100L * 1024 * 1024 * 1024; está especificando que uno de los valores es long (aquí 100L) y la multiplicación con ese valor resulta en long valor que se almacena correctamente en a2

En Java, si tiene int * int, calculará la salida como un int. Solo da el resultado como un largo si lo haces INT * largo. En su caso, el 100 * 1024 * 1024 * 1024 tiene un resultado que desborda Int.

Entonces, agregar una "L" hace que el operando sea largo, y el cálculo almacena los valores en mucho tiempo. Y, por supuesto, no se produce desbordamiento y se puede generar un resultado correcto (es decir, A2).

El número 3 funcionó porque especificó un tipo largo que es 100L. Es por eso que es una multiplicación larga y podría almacenarse. Por otro lado, el número 4 hay una multiplicación entera con el valor máximo 2^32-1, por eso apareció un desbordamiento y el valor predeterminado de cero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top