¿Cómo comparar esa secuencia de dobles son todos "aproximadamente iguales" en Java?

I have a method in java that returns a double number and I want to compare every double number that is returned every time I call the method(say 5 times), so that I can conclude that the number returned is almost the same every time.

¿Cómo puedo hacer esto?

preguntado el 01 de febrero de 12 a las 03:02

Can you say more about the context? Are you doing this from a unit test? In that case, one of the assertEquals in JUnit has just such a method for asserting that two doubles are close. -

Thanks everyone for the replies. So yes, I am trying to do a Unit testing, and my method returns the time that some integers are added to an array. I want to test this method with different amounts of integers and compare the times. I guess the ulp() method might work. -

7 Respuestas

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

Where eps is measure of equality.

Respondido 01 Feb 12, 11:02

I took the liberty of removing an extra ) - Peter Lawrey

Math.abs((a-b)/a)<eps is an alternative that doesn't require that eps depend on the magnitude of a y la b. En este caso, eps is like the percent difference rather than the magnitude difference that is tolerable. Be careful about divide by zero though. - sffc

You must first decide what "almost the same" means. For example, there's a method in java.lang.Math llamado ulp() which, given a double, returns the distance between that double and the next; i.e., the smallest possible difference between that number and any other. You might simply compare the difference between the two doubles and the result of calling that method.

On the other hand, maybe you want two numbers to just be within 1% of eachother. In that case, do the same computation, but use the first number multiplied by 0.01 en lugar de ulp() as the largest acceptable distance.

Respondido 01 Feb 12, 07:02

Thanks everyone for the replies. So yes, I am trying to do a Unit testing, and my method returns the time that some integers are added to an array. I want to test this method with different amounts of integers and compare the times. I guess the ulp() method might work. - FranXh

Approximate equality is defined in terms of the absolute difference: if an absolute difference does not exceed a certain, presumably small, number, then you can say that the values you are comparing are "close enough".

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

You must be very careful to not confuse "close enough" end "equals", because the two are fundamentally different: equality is transitive (i.e. a==b and b==c together imply that a==c), while "close enough" is not transitive.

Respondido 01 Feb 12, 07:02

It depends on what you mean by similar. If you want to compare two numbers within an absolute error e.g. 1e-6 you can use epsilon. If you want to compare two double regardless of scale. e.g. 1.1e-20 and 1.3e-20 are not similar but 1.1e20 and 1.1e20+1e5 are you can compare the raw value.

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

Respondido 01 Feb 12, 11:02

Careful with the common pattern of comparing a difference to 0 with this. Around 0 it becomes suddenly very sensitive: similarUnscaled(0.69 / 3, 0.23, 10) != similarUnscaled(0.69 / 3 - 0.23, 0, 10) - Georg

Podrías usar Guayaba y la DoubleMath#fuzzyEquals method (since version 13.0):

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

Returns true if a and b are within tolerance of each other. Technically speaking, this is equivalent to Math.abs(a - b) <= tolerance || Double.valueOf(a).equals(Double.valueOf(b)).

Notable special cases include:

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

Respondido 17 Abr '18, 11:04

What does it mean for two doubles to be "approximately equal?" It means that the doubles are within some tolerance of each other. The size of that tolerance, and whether that tolerance is expressed as an absolute number or as a percentage of the two doubles, depends on your application.

For instance, two photos displayed on a photo viewer have approximately the same width in inches if they take up the same number of pixels on the screen, so your tolerance will be an absolute number calculated based on pixel size for your screen. On the other hand, two financial firms' profits are probably "approximately equal" if they are within 0.1% of each other. These are just hypothetical examples, but the point is that it depends on your application.

Now for some implementation. Let's say your application calls for an absolute tolerance. Then you can use

private static final double TOLERANCE = 0.00001;

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

to compare two doubles, and use

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

to compare five doubles.

Respondido 01 Feb 12, 07:02

El Apache commons-math library provides the nice Precision clase (ver Documentos de API), that can compare doubles in different ways:

Precision.equals(a, b, 0.1); // Tell if |a-b| <= 0.1
Precision.equals(a, b, 10); // Tell if a and b are less than 10 Ulps apart
Precision.equalsWithRelativeTolerance(a, b, 0.05); // Tell if a and b are less than 5% apart

Respondido 25 Feb 20, 01:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.