Java:Agregar Double.MIN_NORMAL a un doble no cambia el número
-
21-12-2019 - |
Pregunta
Pensé que MIN_NORMAL era un valor que podías agregar a un doble "normal" y el número cambiaría.P.ej.agregue Double.MIN_NORMAL a 0.1d y obtendrá un valor diferente de 0.1d, sin embargo, mi entendimiento es incorrecto:
public static void test(double val) {
if (val == (val - Double.MIN_NORMAL*1e50d))
System.out.printf("val == (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
else
System.out.printf("val != (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
}
Que produce:
test(0.0d);
> val != (val - Double.MIN_NORMAL*1e50d) for val=0.00000000000000000000
test(1.0d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=1.00000000000000000000
test(0.1d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=0.10000000000000000000
Que alguien explique qué va en contra de mi lógica aquí, que incluso si sumo MIN_NORMAL multiplicado por 1e50d, sigo obteniendo el mismo número.
Revisé las representaciones binarias y 1 * Double.MIN_NORMAL es diferente de 2 * Double.MIN_NORMAL, pero restarlas de cualquier valor excepto cero no cambia el número original.
Solución
MIN_NORMAL
es, como dice el Javadoc, sólo el más pequeño normalizado double
valor.Pero eso no significa que sea algo como 1
para int
s:Para valores de punto flotante, simplemente existe No "eps" estándar que puede agregar para cambiar al siguiente valor representable; los "eps" siempre dependen del exponente del valor de punto flotante dado.Por eso se llaman flotante puntos, al final :)
Sin embargo, Java 1.6+ proporciona Math.nextAfter()
que devuelve, para cualquier dado double
, el siguiente o anterior representable double
.
En versiones anteriores de Java, siempre puedes trastear con Double.doubleToLongBits()
, incrementando o disminuyendo su resultado y volviendo a convertir por Double.longBitsToDouble()
;esto te da el representable siguiente o anterior double
valor -- en la mayoría de los casos:Hay algunos casos especiales (NaN, valores infinitos), por lo que no se recomienda esto para principiantes en punto flotante :)
Otros consejos
Double tiene una precisión limitada.Min_Normal es 2E-1022.Se reducirá a menos que el número que lo agregue a la que lo agregue también está en el estadio Ballpark de 2E-1000.