In my python program, an if statement is not being entered. I have simplified the code to the following:
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
This program does not output anything.
However, changing the last line to x += .5 makes the program output 0. What's the problem?
I suggest you say x > -.001 and x < .001 or something of the sort
Floating point number representation might not be accurate enough. You should never test for zero equality but instead use something along
In binary, .01 has no exact representation but .5 does.
It's the same problem you'd have in decimal if you represented 1/3 as .333333 and kept adding 1/3 until you reached 1. After three additions, you'd have .999999 which is not exactly equal to 1.
Don't compare non-integers for equality unless you precisely understand the rules for doing so and are 100% sure your case is one of the ones that will work.
Others have pointed out the issue with floating-point numbers being unable to represent values exactly. If you need exact decimal representation of a number, you can use the
Decimal
class:This will print
0
as you expect.Note the use of a string for the increment. If you used
Decimal(.01)
you'd have the same problem with accurate representation of 0.01, because you're converting from a floating-point number and have already lost the accuracy, so the class doesn't allow that.Behold the power of the print statement...
Let us insert a print statement...
Running this program, and inspecting the output around 0 reveals the problem:
Oh boy, it is never actually equal to zero!
Solutions:
Use integers. Most reliable.
Never test equality with floating point arithmetic, but rather use a range:
This is a rounding issue - decimal values cannot be represented exactly in binary, so x never exactly equals 0.0000000000....
try replacing
if (x == 0):
withif -0.001 < x < 0.001:
BTW, the parentheses are unnecessary in a python
if
statement.edit: Printing out the values between -1 and 1 in steps of 0.01 shows this is the case - where zero should be it prints 7.52869988574e-16.