954,219 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Python bug??? Or just a stupid question?

Hello,
I am a newbie in Python and maybe this is a stupid question, but when I run this code I receive a very strange output.

status = 0
for i in range(10):
    status = status + 0.1        
        
    if status == 0.1:
        print status
    elif status == 0.2:
        print status
    elif status == 0.3:
        status
    elif status == 0.4:
        print status
    elif status == 0.5:
        print status
    elif status == 0.6:
        print status
    elif status == 0.7:
        print status
    elif status == 0.8:
        print status
    elif status == 0.9:
        print status
    elif status == 1.0:
        print status

At first I supposed that I will receive something like this:
>>>
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
>>>

But finally I was really surprised. Output looks like this:
>>>
0.1
0.2
0.4
0.5
0.6
0.7
>>>

Could somebody tells me what I am doing wrong?

tesak
Newbie Poster
2 posts since Oct 2007
Reputation Points: 10
Solved Threads: 0
 

This happens with many computer languages. You are trying to compare floating point values directly. Your 0.8 might be more like 0.799999999999999 and the compare flunks!

You can make this work by giving it a range you can compare within ...

if 0.79999 < status < 0.80001:
    ... do something`
vegaseat
DaniWeb's Hypocrite
Moderator
5,976 posts since Oct 2004
Reputation Points: 1,345
Solved Threads: 1,416
 

Look at the line following
elif status == 0.3:
And why do you have if/elif? Why not just print the value?

woooee
Nearly a Posting Maven
2,454 posts since Dec 2006
Reputation Points: 777
Solved Threads: 714
 

Thanks for an answer. It was just an example which really surprise me. But is there a way how to compare two float numbers without unpredictable results?

tesak
Newbie Poster
2 posts since Oct 2007
Reputation Points: 10
Solved Threads: 0
 

Well, there are actually three issues in the code:

(1) is a matter of efficiency, which woooee already raised.

status = 0
for i in range(10):
    status = status + 0.1        
    print status


does what you wanted to do, and is cleaner to read. One payoff of this approach is that...

(2) ...in your original code, you didn't get 0.3 in the output because you left out the print statement. The lines

elif status == 0.3:
    status


have the effect of evaluating, but not printing, status. And then throwing away the result, because you aren't doing anything with it.

(3) Finally, comparing floating points is a common source of bugs. Even if we worked with BCD, so that we didn't have to work about base-2 to base-10 errors, still and all, our decimal approximations would still lead to imprecision. For example, the test π == 3.14159265358979 is False.

Vega gives a very good approach to this by selecting a range. My own approach is to define a function that is in my code base:

def fuzzyequals(a,b,epsilon = 0.0001):
   return abs(a-b) < epsilon


This function returns True if a is within the "halo" of b; that is, if b-epsilon < a < b+epsilon.

You can then use it like this:

...
if fuzzyequals(status,0.2):      # or fuzzyequals(status, 0.2, 0.01)
   print status
...

Hope that helps,
Jeff

jrcagle
Practically a Master Poster
608 posts since Jul 2006
Reputation Points: 92
Solved Threads: 156
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You