El siguiente bloque de códigos da la salida como 0.
public class HelloWorld{
public static void main(String []args){
int product = 1;
for (int i = 10; i <= 99; i++) {
product *= i;
}
System.out.println(product);
}
}
¿Alguien puede explicar por qué sucede esto?
java
integer
integer-overflow
Aniruddha Sarkar
fuente
fuente
2
aparecerá aproximadamente 90 veces. Eso significa que necesitará una variable con al menos 90 bits para obtener una salida distinta de cero. 32 y 64 son menos de 90. Para calcular enteros más grandes que las palabras nativas, debe usar cualquier clase de enteros grandes que esté disponible en el idioma elegido.Respuestas:
Esto es lo que hace el programa en cada paso:
Observe que en algunos pasos la multiplicación da como resultado un número menor (980179200 * 18 = 463356416) o un signo incorrecto (213837312 * 20 = -18221056), lo que indica que hubo un desbordamiento de enteros. ¿Pero de dónde viene el cero? Sigue leyendo.
Teniendo en cuenta que
int
el tipo de datos es un signo de 32 bits , de complemento a dos enteros, aquí es una explicación de cada paso:Sabemos que multiplicar un número por un número par:
Entonces, básicamente, su programa multiplica un número par con otro número repetidamente, lo que pone a cero los bits de resultados comenzando desde la derecha.
PD: Si las multiplicaciones involucraron números impares solo entonces el resultado no será cero.
fuente
La multiplicación por computadora realmente está sucediendo en el módulo 2 ^ 32. Una vez que haya acumulado suficientes potencias de dos en el multiplicando, todos los valores serán 0.
Aquí tenemos todos los números pares de la serie, junto con la potencia máxima de dos que divide el número y la potencia acumulada de dos.
El producto hasta 42 es igual a x * 2 ^ 32 = 0 (mod 2 ^ 32). La secuencia de los poderes de dos está relacionada con los códigos Gray (entre otras cosas), y aparece como https://oeis.org/A001511 .
EDITAR: para ver por qué otras respuestas a esta pregunta son incompletas, considere el hecho de que el mismo programa, restringido solo a enteros impares, no convergería a 0, a pesar de todo el desbordamiento.
fuente
Parece un desbordamiento de enteros .
Mira esto
Salida:
La salida ya no será un
int
valor. Entonces obtendrá un valor incorrecto debido al desbordamiento.Más información
Editar .
Cambiemos su código de la siguiente manera
Fuera puesto:
fuente
Es debido al desbordamiento de enteros. Cuando multiplica muchos números pares, el número binario obtiene muchos ceros finales. Cuando tiene más de 32 ceros finales para un
int
, se desplaza a0
.Para ayudarlo a visualizar esto, aquí están las multiplicaciones en hexadecimal calculadas en un tipo de número que no se desbordará. Vea cómo crecen lentamente los ceros finales y observe que un
int
está formado por los últimos 8 dígitos hexadecimales. Después de multiplicar por 42 (0x2A), ¡todos los 32 bits de anint
son ceros!fuente
En algún lugar en el medio se obtiene
0
como producto. Entonces, todo su producto será 0.En tu caso :
Cada vez que multiplica el valor actual de
i
con el número que obtiene0
como salida.fuente
Dado que muchas de las respuestas existentes apuntan a detalles de implementación de Java y salida de depuración, echemos un vistazo a las matemáticas detrás de la multiplicación binaria para responder realmente por qué.
El comentario de @kasperd va en la dirección correcta. Suponga que no se multiplica directamente con el número, sino con los factores primos de ese número. Que muchos números tendrán 2 como factor primo. En binario, esto es igual a un desplazamiento a la izquierda. Por conmutatividad podemos multiplicar con factores primos de 2 primero. Eso significa que solo hacemos un desplazamiento a la izquierda.
Al echar un vistazo a las reglas de multiplicación binaria, el único caso en que un 1 dará como resultado una posición de dígitos específica es cuando ambos valores de operando son uno.
Entonces, el efecto de un desplazamiento a la izquierda es que la posición de bit más baja de un 1 cuando se multiplica aún más el resultado aumenta.
Dado que el entero contiene solo los bits de orden más bajo, todos se establecerán en 0 cuando el factor primo 2 se combina con la frecuencia suficiente en el resultado.
Tenga en cuenta que la representación del complemento a dos no es de interés para este análisis, ya que el signo del resultado de la multiplicación puede calcularse independientemente del número resultante. Eso significa que si el valor se desborda y se vuelve negativo, los bits de orden más bajo se representan como 1, pero durante la multiplicación se tratan nuevamente como 0.
fuente
Si ejecuto este código, lo que obtengo es todo:
Causa de desbordamiento de enteros:
Producir 0 causa -
fuente
Eventualmente, el cálculo se desborda, y eventualmente ese desbordamiento conduce a un producto de cero; eso sucede cuando
product == -2147483648
yi == 42
. Pruebe este código para verificarlo usted mismo (o ejecute el código aquí ):Una vez que es cero, por supuesto, permanece cero. Aquí hay un código que producirá un resultado más preciso (puede ejecutar el código aquí ):
fuente
Es un desbordamiento de enteros.
El tipo de datos int es de 4 bytes o 32 bits. Por lo tanto, los números mayores que 2 ^ (32 - 1) - 1 (2,147,483,647) no se pueden almacenar en este tipo de datos. Sus valores numéricos serán incorrectos.
Para números muy grandes, querrá importar y usar la clase
java.math.BigInteger:
NOTA: Para valores numéricos que todavía son demasiado grandes para el tipo de datos int, pero lo suficientemente pequeños como para caber dentro de 8 bytes (valor absoluto menor o igual a 2 ^ (64 - 1) - 1), probablemente debería usar la
long
primitiva.Los problemas de práctica de HackerRank (www.hackerrank.com), como la sección de práctica de Algoritmos, ( https://www.hackerrank.com/domains/algorithms/warmup ) incluyen algunas muy buenas preguntas de gran número que dan buenas prácticas sobre cómo pensar en el tipo de datos apropiado para usar.
fuente