1

I am testing a random formula I was wondering about. After writing the code to test out the formula, most were true but some were false. I noticed, however that in my print statement, both sides of the equation were equal, but the code said they weren't.

Here is the code:

public static void main(String[] args){
        for(int i = 0; i < 100; i++){
            String t = runTest((100-i)/100.0,i/100.0);
            if(t.substring(0, 1).equals("1")) System.err.println(t);
            else System.out.println(t.substring(1));
        }
    }

    private static String runTest(double a, double b){
        double l = (a + b);
        double r = (a*a + b*b + 2*a*b);
        boolean isValid = false;
        if(l != 1) {
            return 1+String.format("%f + %f = %f\tInvalid", a, b, a + b);
        }
        if(l==r){
            isValid = true;
        }

        return 0+String.format("A: %f B: %f LEFT: %f RIGHT: %f RESULT: %s", a, b, l, r, String.valueOf(isValid));
    }

I have also tried to cast l and r to an integer and r returns 0 sometimes meaning that the code thinks that r is below 0. In reality and the print statement, the right side is also 1. I thought at first that it was a floating point error but in both sides ended up as 1.

Do you know why this is happening and how I could fix this?

Thanks.

Meeesh
  • 992
  • 1
  • 8
  • 15

2 Answers2

4

Comparing floating point numbers for equality using the == operator is bad practise.

You must include a tolerance.

final float T = 0.0000001;
if (Math.abs(l - r) < T)
  isValid = true;

Modify T such that it fits your needs.

Community
  • 1
  • 1
Pétur Ingi Egilsson
  • 4,368
  • 5
  • 44
  • 72
1

run this

public class Test {
public static void main(String[] args){
    for(int i = 0; i < 100; i++){
        String t = runTest((100-i)/100.0,i/100.0);
        if(t.substring(0, 1).equals("1")) System.err.println(t);
        else System.out.println(t.substring(1));
    }
}

private static String runTest(double a, double b){
    double l = (a + b);
    double r = (a*a + b*b + 2*a*b);
    boolean isValid = false;
    if(l != 1) {
        //return 1+String.format("%f + %f = %f\tInvalid", a, b, a + b);
        return  a + ":" + b+ ":" +  a  +  b ;
    }
    if(l==r){
        isValid = true;
    }
    return  a + ":" + b+ ":" +  l + ":" +  r ;
 }

}

so yes, they look equal when formatted as floats, but they aren doubles (64bit) which is how you compare them (and as such they are not equal as you can see from the output of the code I posted).

Ueli Hofstetter
  • 2,409
  • 4
  • 29
  • 52