rtheunissen
rtheunissen

Reputation: 7435

How to avoid rounding errors of double values in conditionals?

At the moment this is what my code looks like:

if (!flipped){
    scaleX -= 0.1;
    if (scaleX < 0.0001){
      sounds.playSound("flick");
      flipped = true;
   }
 }

Here is what I'd like it to look like:

if (!flipped){
    scaleX -= 0.1;
    if (scaleX == 0){
      sounds.playSound("flick");
      flipped = true;
   }
 }

How can I achieve this? Because the double value (scaleX) is never actually 0.

Upvotes: 0

Views: 948

Answers (4)

darma
darma

Reputation: 4747

Depending on the usage of your variables, you may want to use the BigDecimal class.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500675

You want to define some sort of tolerance, then do:

if (Math.abs(scaleX) < tolerance)

You shouldn't be checking for the value being exactly zero - just "close enough to zero". That's just a way of life with binary floating point types... things like "0.1" and "0.0001" aren't exactly representable in binary floating point, which is why you run into this sort of thing.

It's not clear why you don't like your original code, and why you want it to be the second form. Other than not taking the absolute value, the first code looks okay to me. (I'd extract out the constant, but that's a separate matter.)

Upvotes: 2

djna
djna

Reputation: 55907

When working with floating point arithmetic it's quite usual to write conceptually a "pretty close to" rather than equals.

 if ( x - y < verySmallValue )

rather than

 if ( x == y )

your y is 0, so you are writing

 if ( x < verySmallValue)

which I think is fine in concept.

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691755

You can't, because floating-point math can't produce exact results given that there are only 2^64 double values to represent an inifinity of numbers.

Upvotes: 1

Related Questions