una - truncar decimales java
¿Cómo prevenir el desbordamiento de enteros en el código Java? (4)
Es un problema difícil desde la perspectiva de la ingeniería.
El sitio de codificación segura recomienda:
- uso de condiciones previas; es decir, compruebe el rango de las entradas para que el desbordamiento sea imposible,
- realizar cada operación aritmética individual utilizando el siguiente tipo entero primitivo más grande y verificar explícitamente el desbordamiento, o
- utilizando BigInteger.
Este artículo del Dr. Dobbs sugiere crear una biblioteca de métodos aritméticos primitivos que realicen cada operación primitiva con una comprobación de desbordamiento explícita. (Podría ver esto como una implementación del punto # 2 anterior). Pero los autores van más lejos al sugerirle que utilice la reescritura de bytecode para reemplazar los bytecodes aritméticos con llamadas a los métodos equivalentes que incorporan controles de desbordamiento.
Desafortunadamente, no hay manera de habilitar la comprobación de desbordamiento de forma nativa en Java. (Pero lo mismo se aplica en muchos otros idiomas; por ejemplo, C, C ++ ...)
Posible duplicado:
¿Cómo puedo verificar si multiplicar dos números en Java causará un desbordamiento?
Supongamos que tengo un método de clase Java, que utiliza las operaciones *
y +
.
int foo(int a, int b) { ... // some calculations with + and * }
¿Cómo asegurarse de que no se produzca un desbordamiento en foo
?
Supongo que puedo usar BigDecimal
o reemplazar todos + y * con "envoltorios" como:
int sum(int a, int b) { int c = a + b; if (a > 0 && b > 0 && c < 0) throw new MyOverfowException(a, b) return c; } int prod(int a, int b) { int c = a * b; if (a > 0 && b > 0 && c < 0) throw new MyOverfowException(a, b) return c; }
¿Hay mejores maneras de asegurarse de que no se produzca un desbordamiento int
en un método Java?
Suma: compruebe si b es mayor que la diferencia del valor máximo que puede almacenar en int menos el valor de a. Si a y / o b pueden ser negativos, debe (i) tener cuidado de no obtener un desbordamiento ya para la comprobación de diferencias y (ii) realizar una comprobación similar para el mínimo.
Producto: Eso es más difícil. Dividiría los enteros en dos enteros de media longitud (es decir, si int es de 32 bits, los dividiría en dos números de 16 bits usando enmascaramiento y desplazamiento de bits). Luego haga la multiplicación y luego observe si el resultado se ajusta a 32 bits.
Todo bajo la condición de que no desea simplemente tomar long
para el resultado temporal.
Supongamos que a y b son positivos o negativos, y si el signo de a + b no es igual al signo de a y b, entonces ocurre un desbordamiento. Puede usar esta regla para juzgar si ocurre un desbordamiento y lanzar una excepción. Cuando detecte esta excepción, puede tratarla de acuerdo con el método mencionado en las respuestas anteriores. Otro método es hacer la operación utilizando el tipo de rango más grande que no se desbordará. Puedes usar largo para la operación entre enteros.
Una forma de verificar un desbordamiento es hacer que los operandos se conviertan a un tipo más grande (del doble de la longitud de bit del operando original) y luego realizar la operación, y luego ver si el valor resultante es demasiado grande para el tipo original, por ejemplo
int sum(int a, int b) {
long r = (long)a + b;
if (r >>> 32 != 0) { // no sign extension
throw new MyOverflowException(a, b);
}
return (int)r;
}
Si su tipo original es long
, tendría que usar BigInteger
como ese tipo más grande.