una priorizada prioridad pila ordenar metodos estructura eliminar elemento ejemplos ejemplo datos con como colas cola arreglos java equality floating-accuracy

priorizada - como eliminar un elemento de una pila en java



¿Qué hay de malo con el uso de== para comparar flotadores en Java? (21)

De acuerdo con esta página java.sun == es el operador de comparación de igualdad para números de coma flotante en Java.

Sin embargo, cuando escribo este código:

if(sectionID == currentSectionID)

en mi editor y ejecuta el análisis estático, obtengo: "JAVA0078 Valores de punto flotante en comparación con =="

¿Qué hay de malo con el uso de == para comparar valores de coma flotante? ¿Cuál es la forma correcta de hacerlo?


¿Qué hay de malo con el uso de == para comparar valores de coma flotante?

Porque no es verdad que 0.1 + 0.2 == 0.3


¿Está tratando con un código subcontratado que usaría flotadores para cosas llamadas sectionID e currentSectionID? Sólo curioso.

@Bill K: "La representación binaria de un flotador es un poco molesta". ¿Cómo es eso? ¿Cómo lo harías mejor? Hay ciertos números que no se pueden representar en ninguna base correctamente, porque nunca terminan. Pi es un buen ejemplo. Solo puedes aproximarlo. Si tiene una mejor solución, comuníquese con Intel.


A partir de hoy, la manera rápida y fácil de hacerlo es:

if (Float.compare(sectionID, currentSectionID) == 0) {...}

Sin embargo, los docs no especifican claramente el valor de la diferencia de margen (un épsilon de la respuesta de @Victor) que siempre está presente en los cálculos en flotantes, pero debe ser algo razonable ya que forma parte de la biblioteca de lenguaje estándar.

Sin embargo, si se necesita una precisión más alta o personalizada, entonces

float epsilon = Float.MIN_NORMAL; if(Math.abs(sectionID - currentSectionID) < epsilon){...}

es otra opción de solución.


Además de las respuestas anteriores, debes tener en cuenta que existen comportamientos extraños asociados con -0.0f y +0.0f (son == pero no son equals ) y Float.NaN (es equals pero no == ) (espero que yo '' tengo derecho - argh, ¡no lo hagas!).

Editar: ¡Comprobemos!

import static java.lang.Float.NaN; public class Fl { public static void main(String[] args) { System.err.println( -0.0f == 0.0f); // true System.err.println(new Float(-0.0f).equals(new Float(0.0f))); // false System.err.println( NaN == NaN); // false System.err.println(new Float( NaN).equals(new Float( NaN))); // true } }

Bienvenido a IEEE / 754.


Antes que nada, ¿flotan o flotan? Si uno de ellos es un Float, debe usar el método equals (). Además, probablemente sea mejor utilizar el método estático Float.compare.



Como se menciona en otras respuestas, los dobles pueden tener pequeñas desviaciones. Y podría escribir su propio método para compararlos usando una desviación "aceptable". Sin embargo ...

Hay una clase apache para comparar dobles: org.apache.commons.math3.util.Precision

Contiene algunas constantes interesantes: SAFE_MIN y EPSILON , que son las desviaciones máximas posibles de las operaciones aritméticas simples.

También proporciona los métodos necesarios para comparar, igualar o redondear dobles. (usando ulps o desviación absoluta)


Creo que hay mucha confusión sobre los flotadores (y los dobles), es bueno aclararlo.

  1. No hay nada intrínsecamente incorrecto en el uso de flotantes como ID en JVM estándar [*]. Si simplemente configura la identificación del flotador en x, no hace nada con ella (es decir, no tiene aritmética) y luego prueba con y == x, estará bien. Además, no hay nada de malo en usarlos como claves en un HashMap. Lo que no se puede hacer es asumir igualdades como x == (x - y) + y , etc. Dicho esto, las personas generalmente usan tipos enteros como ID, y se puede observar que la mayoría de las personas están desilusionadas por este código, por lo que razones prácticas, es mejor adherirse a las convenciones. Tenga en cuenta que hay tantos valores double diferentes como values largos, por lo que no gana nada al usar el double . Además, generar "próxima ID disponible" puede ser complicado con dobles y requiere algún conocimiento de la aritmética de coma flotante. No vale la pena el problema.

  2. Por otro lado, confiar en la igualdad numérica de los resultados de dos cálculos matemáticamente equivalentes es arriesgado. Esto se debe a los errores de redondeo y la pérdida de precisión al convertir de representación decimal a binaria. Esto ha sido discutido hasta la muerte en SO.

[*] Cuando dije "JVM compatible con el estándar", quise excluir ciertas implementaciones de JVM con daño cerebral. Mira this


Dos cálculos diferentes que producen números reales iguales no producen necesariamente números de coma flotante iguales. Las personas que usan == para comparar los resultados de los cálculos generalmente terminan sorprendiéndose por esto, por lo que la advertencia ayuda a marcar lo que de otra manera podría ser un error sutil y difícil de reproducir.


En una respuesta de una línea puedo decir, debes usar:

Float.floatToIntBits(sectionID) == Float.floatToIntBits(currentSectionID)

Para hacerte aprender más sobre el uso correcto de operadores relacionados, aquí estoy elaborando algunos casos: en general, hay tres formas de probar cadenas en Java. Puede usar ==, .equals () u Objects.equals ().

¿En qué se diferencian? == prueba la calidad de referencia en cadenas, lo que significa averiguar si los dos objetos son iguales. Por otro lado, .equals () prueba si las dos cadenas tienen el mismo valor lógicamente. Finalmente, Objects.equals () prueba cualquier nulo en las dos cadenas y luego determina si se llama a .equals ().

Operador ideal para usar

Bueno, esto ha estado sujeto a muchos debates porque cada uno de los tres operadores tiene su conjunto único de fortalezas y debilidades. Ejemplo, == es a menudo una opción preferida cuando se compara la referencia de objeto, pero hay casos en los que también puede parecer que se comparan valores de cadena.

Sin embargo, lo que obtienes es un valor de caída porque Java crea una ilusión de que estás comparando valores, pero en el sentido real no lo eres. Considere los dos casos a continuación:

Caso 1:

String a="Test"; String b="Test"; if(a==b) ===> true

Caso 2

String nullString1 = null; String nullString2 = null; //evaluates to true nullString1 == nullString2; //throws an exception nullString1.equals(nullString2);

Por lo tanto, es mucho mejor usar cada operador al probar el atributo específico para el que está diseñado. Pero en casi todos los casos, Objects.equals () es un operador más universal, por lo tanto, la experiencia de los desarrolladores web lo opta.

Aquí puede obtener más detalles: http://fluentthemes.com/use-compare-strings-java/


Este es un problema no específico de Java. Usar == para comparar dos flotantes / dobles / cualquier número de tipo decimal puede potencialmente causar problemas debido a la forma en que se almacenan. Un flotador de precisión simple (según el estándar IEEE 754) tiene 32 bits, distribuidos de la siguiente manera:

1 bit - Signo (0 = positivo, 1 = negativo)
8 bits - Exponente (una representación especial (sesgo-127) de la x en 2 ^ x)
23 bits - Mantisa. El número actual que está almacenado.

La mantisa es lo que causa el problema. Es como una notación científica, solo el número en la base 2 (binario) se parece a 1.110011 x 2 ^ 5 o algo similar. Pero en binario, el primer 1 es siempre un 1 (a excepción de la representación de 0)

Por lo tanto, para ahorrar un poco de espacio en la memoria (juego de palabras intencionado), IEEE decidió que el 1 debería ser asumido. Por ejemplo, una mantisa de 1011 realmente es 1.1011.

Esto puede causar algunos problemas con la comparación, especialmente con 0 ya que 0 no puede representarse exactamente en un flotante. Esta es la razón principal por la cual se desaconseja el ==, además de los problemas matemáticos de punto flotante descritos por otras respuestas.

Java tiene un problema único en el sentido de que el lenguaje es universal en muchas plataformas diferentes, cada una de las cuales puede tener su propio formato flotante único. Eso hace que sea aún más importante evitar ==.

La forma correcta de comparar dos carrozas (la mente que no es específica del idioma) para la igualdad es la siguiente:

if(ABS(float1 - float2) < ACCEPTABLE_ERROR) //they are approximately equal

donde ACCEPTABLE_ERROR está # definido o alguna otra constante igual a 0.000000001 o cualquier precisión que se requiera, como Víctor ya mencionó.

Algunos idiomas tienen esta funcionalidad o esta constante incorporada, pero generalmente es un buen hábito para estar.


La forma correcta sería

java.lang.Float.compare(float1, float2)


Lo siguiente usa automáticamente la mejor precisión:

/** * Compare to floats for (almost) equality. Will check whether they are * at most 5 ULP apart. */ public static boolean isFloatingEqual(float v1, float v2) { if (v1 == v2) return true; float absoluteDifference = Math.abs(v1 - v2); float maxUlp = Math.max(Math.ulp(v1), Math.ulp(v2)); return absoluteDifference < 5 * maxUlp; }

Por supuesto, puede elegir más o menos de 5 ULP (''unidad en el último lugar'').

Si está interesado en la biblioteca Apache Commons, la clase Precision tiene compareTo() y equals() con epsilon y ULP.


Los valores de punto flotante pueden estar un poco desfasados, por lo que es posible que no se informen exactamente igual. Por ejemplo, establecer un flotante en "6.1" y luego imprimirlo de nuevo, puede obtener un valor reportado de algo así como "6.099999904632568359375". Esto es fundamental para el funcionamiento de las carrozas; por lo tanto, no desea compararlos usando la igualdad, sino más bien la comparación dentro de un rango, es decir, si la diferencia del flotante con el número con el que desea comparar es menor que un cierto valor absoluto.

This artículo en el Registro ofrece una buena visión general de por qué este es el caso; lectura útil e interesante.


Los valores del punto de lanzamiento no son confiables, debido a un error de redondeo.

Como tal, probablemente no deberían usarse como valores clave, como sectionID. Use enteros en su lugar, o long si int no contiene suficientes valores posibles.


Puedes usar Float.floatToIntBits ().

Float.floatToIntBits(sectionID) == Float.floatToIntBits(currentSectionID)



Solo para dar la razón detrás de lo que dicen los demás.

La representación binaria de un flotador es un poco molesto.

En binario, la mayoría de los programadores conocen la correlación entre 1b = 1d, 10b = 2d, 100b = 4d, 1000b = 8d

Bueno, también funciona a la inversa.

.1b = .5d, .01b = .25d, .001b = .125, ...

El problema es que no hay una forma exacta de representar la mayoría de los números decimales como .1, .2, .3, etc. Todo lo que puedes hacer es aproximado en binario. El sistema hace un pequeño rodeo cuando los números se imprimen para que muestre .1 en lugar de .10000000000001 o .999999999999 (que probablemente estén tan cerca de la representación almacenada como .1)

Editar del comentario: la razón por la cual este es un problema son nuestras expectativas. Esperamos completamente que 2/3 se distorsionen en algún momento cuando lo convertimos a decimal, ya sea .7 o .67 o .666667. Pero no esperamos automáticamente que .1 se redondee de la misma manera que 2/3 - y eso es exactamente lo que está pasando.

Por cierto, si tiene curiosidad, el número que almacena internamente es una representación binaria pura utilizando una "notación científica" binaria. Entonces, si le dice que almacene el número decimal 10.75d, almacenaría 1010b para el 10 y .11b para el decimal. Entonces almacenaría .101011 y luego guardará algunos bits al final para decir: Mueva el punto decimal cuatro lugares a la derecha.

(Aunque técnicamente ya no es un punto decimal, ahora es un punto binario, pero esa terminología no habría hecho las cosas más comprensibles para la mayoría de las personas que encontrarían útil esta respuesta).


Una forma de reducir el error de redondeo es utilizar el doble en lugar de flotar. Esto no hará que el problema desaparezca, pero sí reducirá la cantidad de errores en su programa y la flotación casi nunca es la mejor opción. EN MI HUMILDE OPINIÓN.


es posible que desee que sea ==, pero 123.4444444444443! = 123.4444444444442


la forma correcta de probar floats para ''igualdad'' es:

if(Math.abs(sectionID - currentSectionID) < epsilon)

donde epsilon es un número muy pequeño como 0.00000001, dependiendo de la precisión deseada.