Asignar valores largos con cuidado en Java para evitar el desbordamiento

Predecir la salida del siguiente programa

public class LongDivision {
    public static void main(String[] args) {
    final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
    final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
  
    }
}

Solución:

Tanto el divisor como el dividendo son de tipo largo, que es fácilmente lo suficientemente grande como para contener cualquiera de los productos sin desbordamiento. Parece, entonces, que el programa debe imprimir 1000. Desafortunadamente, imprime 5 . Qué está pasando aquí? El problema es que el cálculo de la constante MICROS_PER_DAY se desborda. Aunque el resultado del cálculo cabe en un largo con espacio de sobra, no cabe en un int. El cálculo se realiza completamente en aritmética int, y solo después de que se completa el cálculo, el resultado se promueve a largo. Para entonces, ya es demasiado tarde: el cómputo ya se ha desbordado.
La promoción de int a long es una conversión primitiva de ampliación, que conserva el valor numérico (incorrecto). Luego, este valor se divide por MILLIS_PER_DAY, que se calculó correctamente porque cabe en un int. El resultado de esta división es 5. Entonces, ¿por qué se realiza el cálculo en aritmética int? Porque todos los factores que se multiplican juntos son valores enteros.
Cuando multiplicas dos valores int, obtienes otro valor int. Java no tiene tipificación de destino, una característica del lenguaje en la que el tipo de la variable en la que se almacenará un resultado influye en el tipo de cálculo.. Es fácil arreglar el programa usando un literal largo en lugar de un int como el primer factor en cada producto. Esto obliga a que todos los cálculos subsiguientes en la expresión se realicen con aritmética larga. Si bien es necesario hacerlo solo en la expresión para MICROS_PER_DAY, es buena forma hacerlo en ambos productos.
Del mismo modo, no siempre es necesario usar un largo como primer valor en un producto, pero es una buena forma de hacerlo. Comenzar ambos cálculos con valores largos deja en claro que no se desbordarán. Este programa imprime 1000 como se esperaba:

public class LongDivision {
    public static void main(String[] args) {
    final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
    final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
  
    }
}

Producción:

1000

La lección es simple: cuando trabaje con números grandes, tenga cuidado con el desbordamiento: es un asesino silencioso.

Este artículo es una contribución de Shubham Juneja . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *