2

I'm trying to find possible integer roots of a quadratic equation with Java.

enter image description here

Here is a snippet from my code:

double sqrtDiscriminant = Math.sqrt(b * b - 4 * a * c);

double  root1 = ((-1.0 * b) - sqrtDiscriminant) / (2.0 * a);
double  root2 = ((-1.0 * b) + sqrtDiscriminant) / (2.0 * a);

For a = 2, b = -1 and c = -40755, one of the roots is 143.0 (143.0 is printed to console when I echo it so I'm only interested in such double values, not 143.00001) My question is, how can I make sure that any root has an integer value? If root1 = 143.0 then e.g. root1 == 143 should return true.

I tried root1 == Math.floor(root1) but it didn't work.

Juvanis
  • 25,802
  • 5
  • 69
  • 87
  • maybe root1*1000==Math.floor(root1) * 1000 ? – Kubi Dec 17 '12 at 15:03
  • 1
    I think it would be better to check that `Double.intValue(root1)` when passed to the equation really satisfies it. – Andrew Logvinov Dec 17 '12 at 15:05
  • 1
    You'll never solve this at the numerical level. A finite computing machine is unable to model the full complexity of real numbers. – Marko Topolnik Dec 17 '12 at 15:05
  • See [How to test if a double is an integer][1] [1]: http://stackoverflow.com/questions/9898512/how-to-test-if-a-double-is-an-integer – Amos N. Dec 17 '12 at 15:08
  • You should make clear whether `a, b, c` are actually of some integer data type. If they are, exact verification is possible, otherwise you are in the domain of numeric imprecision and have to deal with it. – MvG Jan 31 '14 at 17:05

7 Answers7

3

You should never use equality checks when working with double-values. Define an accuracy value like

double epsilon = 0.0000001;

Then check whether the difference is nearly equal to epsilon:

if(Math.abs(Math.floor(value)-value) <= epsilon) { }
Simon
  • 9,255
  • 4
  • 37
  • 54
  • You should use round as the rounding error might be slightly less tha the number desired. – Peter Lawrey Dec 17 '12 at 15:08
  • 3
    This tests the wrong thing, it tests whether or not the supposed root is close to an integer; what is needed is a test to determine whether the closest integer to the supposed root is a root of the original equation. – High Performance Mark Dec 17 '12 at 15:09
  • Basically you're right. But choosing enough accuracy will lead to the same result. – Simon Dec 17 '12 at 15:15
2

You can test the integer value if it's a solution also:

x = Math.floor(root1);
if(a*x*x+b*x+c == 0)
...
manji
  • 47,442
  • 5
  • 96
  • 103
  • This answer deals with the ambiguity between two cases: an equation with a root that is almost exactly an integer, and an equation with an integer root that is only approximated by the original solution. However, I think it would be better to use Math.rint to deal with the case of an approximation to an integer solution that is slightly less than the solution. – Patricia Shanahan Dec 17 '12 at 15:09
  • You can't have `²` in an identifier name. – Peter Lawrey Dec 17 '12 at 15:11
2

If I would be you, I will simply take the int/long value of the roots and re-verify the equation to make sure that int/long value of the root is OK or not e.g.

// using round because an equivalent int/long may be represented by a near binary fraction
// as floating point calculations aren't exact
// e.g. 3.999999.. for 4
long longRoot = Math.round(root1); 
if(a*longRoot*longRoot +  b*longRoot + c==0){
    //its valid int root
}else{
    //ignore it
}
vonbrand
  • 11,412
  • 8
  • 32
  • 52
Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • hi yogendra, thanks for the tip. actually using _int_ wouldn't work for some cases in my problem (e.g. large valued roots), but using _long_ definitely helped. – Juvanis Dec 18 '12 at 09:37
1

If you want an integer result use round as your error might mean the number is slightly too large or slightly too small.

long l = Math.round(value);

To round to a fixed number of decimal places you can use

double d = Math.round(value * 1e6) / 1e6; // six decimal places.
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

You can try as

Math.rint(d) == d
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0
if ((variable == Math.floor(variable)) && !Double.isInfinite(variable)) {
    // int
}

If variable is equal to the Math.floor then its Integer. The infinite check is because its will not work for it.

Amos N.
  • 627
  • 10
  • 16
0

the best way will be check whether (Math.floor(root1)-root1)<=0.0000001 It will give you the correct output.

Ranjit Singh
  • 3,715
  • 1
  • 21
  • 35