Search code examples
javafloating-pointnumbers

Float-type useless?


in my java book it told me to not directly compare 2 different float(type) numbers when storing them in variables. Because it gives an approx of a number in the variable. Instead it suggested checking the absolute value of the difference and see if it equals 0. If it does they are the same. How is this helpful? What if I store 5 in variable a and 5 in variable b, how can they not be the same? And how does it help if I compare absolute value??

double a=5,b=5;

if (Math.abs(a-b)==0)
//run code

if (a==b)
//run code 

I don't see at all why the above method would be more accurate? Since if 'a' is not equal to 'b' it wont matter if I use Math.abs.

I appreciate replies and thank you for your time.

I tried both methods.


Solution

  • Inaccuracy with comparisons using the == operator is caused by the way double values are stored in a computer's memory. We need to remember that there is an infinite number of values that must fit in limited memory space, usually 64 bits. As a result, we can't have an exact representation of most double values in our computers. They must be rounded to be saved.

    Because of the rounding inaccuracy, interesting errors might occur:

    double d1 = 0;
    for (int i = 1; i <= 8; i++) {
    d1 += 0.1;
    }
    
    double d2 = 0.1 * 8;
    
    System.out.println(d1);
    System.out.println(d2);
    

    Both variables, d1 and d2, should equal 0.8. However, when we run the code above, we'll see the following results:

    0.7999999999999999
    0.8
    

    In that case, comparing both values with the == operator would produce a wrong result. For this reason, we must use a more complex comparison algorithm.

    If we want to have the best precision and control over the rounding mechanism, we can use java.math.BigDecimal class.

    The recommended algorithm to compare double values in plain Java is a threshold comparison method. In this case, we need to check whether the difference between both numbers is within the specified tolerance, commonly called epsilon:

    double epsilon = 0.000001d;
    
    assertThat(Math.abs(d1 - d2) < epsilon).isTrue();
    

    The smaller the epsilon's value, the greater the comparison accuracy. However, if we specify the tolerance value too small, we'll get the same false result as in the simple == comparison