relacionales precedencia operadores logicos jerarquia ejemplos condicionales comparacion asignacion java floating-point equals-operator

precedencia - El operador ''=='' de Java en dobles



operadores relacionales en java (8)

El resultado de un cálculo de punto flotante es el valor representable más cercano a la respuesta exacta. Este programa:

public class Test { public static void main(String[] args) throws Exception { double val = Double.MAX_VALUE/10; System.out.println(val); System.out.println(Math.nextAfter(val, 0)); } }

huellas dactilares:

1.7976931348623158E307 1.7976931348623155E307

El primero de estos números es tu val original. El segundo es el doble más grande que es menor que él.

Cuando resta 1000 de 1.7976931348623158E307, la respuesta exacta está entre esos dos números, pero muy, muy cerca de 1.7976931348623158E307 que a 1.7976931348623155E307, por lo que el resultado se redondeará a 1.7976931348623155E307, dejando val sin cambios.

Este método devuelve ''verdadero''. Por qué ?

public static boolean f() { double val = Double.MAX_VALUE/10; double save = val; for (int i = 1; i < 1000; i++) { val -= i; } return (val == save); }


Cuando establece val en Double.MAX_VALUE / 10, se establece en un valor aproximadamente igual a 1.7976931348623158 * 10^307 . restar valores como 1000 de eso requeriría una precisión en la representación doble que no es posible, por lo que básicamente deja el val sin cambios.

Según sus necesidades, puede usar BigDecimal lugar de double .


Estás restando un valor bastante pequeño (menos de 1000) de un valor enorme . El valor pequeño es mucho más pequeño que el valor grande que el valor representable más cercano al resultado teórico sigue siendo el valor original.

Básicamente es el resultado de la forma en que funcionan los números flotantes.

Imagina que tenemos algún tipo de coma flotante decimal (solo por simplicidad) que solo almacena 5 dígitos significativos en la mantisa, y un exponente en el rango de 0 a 1000.

Su ejemplo es como escribir 10 999 - 1000 ... pensar cuál sería el resultado, cuando se redondea a 5 dígitos significativos. Sí, el resultado exacto es 99999 ..... 9000 (con 999 dígitos) pero si solo puede representar valores con 5 dígitos significativos, el resultado más cercano es 10 999 nuevamente.


Porque el double es un tipo numérico de coma flotante , que es una forma de aproximar los valores numéricos. Las representaciones de coma flotante codifican números para que podamos almacenar números mucho más grandes o más pequeños de lo que normalmente podríamos. Sin embargo, no todos los números se pueden representar en el espacio dado, por lo que los números múltiples se redondean al mismo valor de coma flotante.

Como un ejemplo simplificado, podríamos querer almacenar valores que van desde -1000 a 1000 en una pequeña cantidad de espacio donde normalmente solo podríamos almacenar -10 a 10. Así que podríamos redondear todos los valores al millar más cercano y almacenarlos en el espacio pequeño: -1000 se codifica como -10 , -900 se codifica como -9 , 1000 se codifica como 10 . Pero, ¿y si queremos almacenar -999? El valor más cercano que podemos codificar es -1000, por lo que tenemos que codificar -999 como el mismo valor que -1000: -10 .

En realidad, los esquemas de coma flotante son mucho más complicados que el ejemplo anterior, pero el concepto es similar. Las representaciones de números flotantes solo pueden representar algunos de todos los números posibles, de modo que cuando tenemos un número que no se puede representar como parte del esquema, tenemos que redondearlo al valor representable más cercano.

En su código, todos los valores dentro de 1000 de Double.MAX_VALUE / 10 automáticamente se redondean a Double.MAX_VALUE / 10 , razón por la cual la computadora piensa (Double.MAX_VALUE / 10) - 1000 == Double.MAX_VALUE / 10 .


Un doble no tiene la precisión suficiente para realizar el cálculo que está intentando. Entonces el resultado es el mismo que el valor inicial.

No tiene nada que ver con el operador == .


Double.MAX_VALUE es tan grande que JVM no distingue entre él y Double.MAX_VALUE-1000

si resta un número menor que "1.9958403095347198E292" de Double.MAV_VALUE el resultado sigue siendo Double.MAX_VALUE .

System.out.println( new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal( Double.MAX_VALUE - 2.E291) ) ); System.out.println( new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal( Double.MAX_VALUE - 2.E292) ) );

Ouptup:

cierto

falso


Double.MAX_VALUE es un número enorme en comparación con 1 o 1000. Double.MAX_VALUE-1 generalmente es igual a Double.MAX_VALUE . Por lo tanto, su código no hace nada al restar 1 o 1000 a Double.MAX_VALUE/10 . Siempre recuerda eso:

  1. double s o float s son solo aproximaciones de números reales, son simplemente racionales no distribuidos equitativamente entre los reales
  2. debe usar operadores aritméticos muy cuidadosamente entre double o float que no están cerca (hay muchas otras reglas como esta ...)
  3. en general, nunca use double s o float si necesita precisión arbitraria

val es un número grande y al restar 1 (o incluso 1000 ) de él, el resultado no se puede expresar correctamente como un valor double . La representación de este número x y x-1 es la misma, porque el double solo tiene un número limitado de bits para representar un número ilimitado de números.