0

I am writing a method which calculates the equation of a 2D Line in the form a*x+b*y=1

//Given two points, find the equation of the line by solving two linear equations and then test the result. (For simplicity, assume that delta !=0 here)

private boolean solveAndRetry(float x1,float y1, float x2,float y2) {
        float delta = x1 * y2 - x2 * y1;
        float deltaA = y2 - y1;
        float deltaB = x1 - x2;

        float a = deltaA / delta;
        float b = deltaB / delta;
        float c = 1;

        //test
        if (a * x2 + b * y2 == c) {
        System.out.println("ok");
            return true;
        }
        else {
            System.out.println(a * x2 + b * y2-c);
            return false;
        }
    }

When I ran it, I was expecting there would be all "ok"s, but that's not the case and I don't know why

public static void main(String[] args) {
        for (float x = 0; x < 10; x += 0.01f) {
            solveAndRetry(1, -1, x, 2);
        }
    }

Here are some lines in the result

ok
ok
ok
ok
ok
ok
ok
ok
-5.9604645E-8
ok
-5.9604645E-8
ok
ok
ok
1.1920929E-7
ok
ok
-5.9604645E-8
ok
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Hải Phong
  • 5,094
  • 6
  • 31
  • 49
  • 2
    [What Every Computer Scientist Should Know About Floating Point](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Don Roby Jan 11 '14 at 14:39
  • 1
    Also: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – Kuba Spatny Jan 11 '14 at 14:40

1 Answers1

3

A float has an accuracy of 6 to 7 decimal digits. Since rounding errors cannot be avoided, your results are as good as it can get.

Normally, you would never compare floating point numbers for equality. Instead of x == y always use a comparison with an interval:

Math.abs(x - y) < eps

for a suitably chosen eps.

Henry
  • 42,982
  • 7
  • 68
  • 84
  • I agree but you think changing the type to decimal or Bigdecimal would change anything ? – Yehia Awad Jan 11 '14 at 14:44
  • 1
    @яша not in principle. You can get more accuracy but there are still real numbers that cannot be represented exactly. – Henry Jan 11 '14 at 14:46
  • In addition you could increase precision by using double instead of float. But this will not prevent you from rounding errors like shown. – isnot2bad Jan 11 '14 at 14:59
  • 2
    @яша BigDecimal is better than float or double at representing decimal fractions exactly, and has adjustable precision. However, there are many rationals such as 1/3 that cannot be exactly represented in BigDecimal, so it would not remove the problem. – Patricia Shanahan Jan 11 '14 at 17:06