round redondear how decimals decimales java double approximation

redondear - java round double to int



¿Cómo comparar esa secuencia de dobles que son "aproximadamente iguales" en Java? (6)

¿Qué significa que dos dobles sean "aproximadamente iguales"? Esto significa que los dobles están dentro de cierta tolerancia entre sí. El tamaño de esa tolerancia, y si esa tolerancia se expresa como un número absoluto o como un porcentaje de los dos dobles, depende de su aplicación.

Por ejemplo, dos fotos que se muestran en un visor de fotos tienen aproximadamente el mismo ancho en pulgadas si ocupan la misma cantidad de píxeles en la pantalla, por lo que su tolerancia será un número absoluto calculado en función del tamaño de píxeles de su pantalla. Por otro lado, las ganancias de dos empresas financieras son probablemente "aproximadamente iguales" si están dentro del 0.1% entre sí. Estos son solo ejemplos hipotéticos, pero el punto es que depende de su aplicación.

Ahora para alguna implementación. Digamos que su aplicación requiere una tolerancia absoluta. Entonces puedes usar

private static final double TOLERANCE = 0.00001; public static boolean approxEqual(final double d1, final double d2) { return Math.abs(d1 - d2) < TOLERANCE; }

para comparar dos dobles, y usar

approxEqual(d1, d2) && approxEqual(d1, d3) && approxEqual(d1, d4) && approxEqual(d1, d5)

para comparar cinco dobles.

Tengo un método en java que devuelve un número doble y quiero comparar cada número doble que se devuelve cada vez que llamo al método (digamos 5 veces), para poder concluir que el número devuelto es casi el mismo cada vez.

¿Cómo puedo hacer esto?


Depende de lo que quieras decir con similar. Si desea comparar dos números dentro de un error absoluto, por ejemplo, 1e-6, puede usar épsilon. Si quieres comparar dos double independientemente de la escala. Por ejemplo, 1.1e-20 y 1.3e-20 no son similares, pero 1.1e20 y 1.1e20 + 1e5 indican que puede comparar el valor bruto.

public static void main(String... args) throws IOException { test(1.1e-20, 1.3e-20); test(1.1e20, 1.1e20 + 1e5); } private static void test(double a, double b) { System.out.println(a + " and " + b + ", similar= " + similarUnscaled(a, b, 10)); } public static boolean similarUnscaled(double a, double b, long representationDifference) { long a2 = Double.doubleToRawLongBits(a); long b2 = Double.doubleToRawLongBits(b); // avoid overflow in a2 - b2 return ((a2 >= 0) == (b2 >= 0)) && Math.abs(a2 - b2) <= representationDifference; }

huellas dactilares

1.1E-20 and 1.3E-20, similar= false 1.1E20 and 1.100000000000001E20, similar= true


La igualdad aproximada se define en términos de la diferencia absoluta: si una diferencia absoluta no excede un número determinado, presumiblemente pequeño, entonces puede decir que los valores que está comparando están "lo suficientemente cerca".

double diff = Math.abs(actual - expected); if (diff < 1E-7) { // Numbers are close enough }

Debe tener mucho cuidado de no confundir "suficientemente cerca" fin "es igual a", porque los dos son fundamentalmente diferentes: la igualdad es transitiva (es decir, a == b y b == c juntos implican que a == c), mientras que "close suficiente "no es transitiva.


Podría usar DoubleMath#fuzzyEquals método DoubleMath#fuzzyEquals Guava y DoubleMath#fuzzyEquals (desde la versión 13.0):

public static boolean fuzzyEquals(double a, double b, double tolerance)

Devuelve true si a y b están dentro de la tolerancia entre sí. Técnicamente hablando, esto es equivalente a Math.abs (a - b) <= tolerancia || Double.valueOf (a) .equals (Double.valueOf (b)).

Los casos especiales notables incluyen:

Enlace a documentos: https://google.github.io/guava/releases/17.0/api/docs/com/google/common/math/DoubleMath.html


Primero debe decidir qué significa "casi lo mismo". Por ejemplo, hay un método en java.lang.Math llamado ulp() que, dado un doble, devuelve la distancia entre ese doble y el siguiente; es decir, la menor diferencia posible entre ese número y cualquier otro. Simplemente puede comparar la diferencia entre los dos dobles y el resultado de llamar a ese método.

Por otro lado, tal vez quiera que dos números solo estén dentro del 1% de cada uno. En ese caso, haga el mismo cálculo, pero use el primer número multiplicado por 0.01 lugar de ulp() como la mayor distancia aceptable.


public static boolean almostEqual(double a, double b, double eps){ return Math.abs(a-b)<eps; }

Donde eps es medida de igualdad.