1

I am trying to make a python script but cant get it to work right. I am dealing with very small numbers and python doesn't seem to like it. Here is my script:

x = 0
while x < 3:
    x += .0001
    if x == 2.5:
        print "X is now: ", x
        break
    else:
        print x

When I run it in PyCharm I get this output (I've shortened it so you don't have to scroll through a bunch of numbers.)

2.4988
2.4989
2.499
2.4991
2.4992
2.4993
2.4994
2.4995
2.4996
2.4997
2.4998
2.4999
2.5
2.5001
2.5002
2.5003
2.5004
2.5005
2.5006
2.5007
2.5008
2.5009
2.501

Pycharm is acting as if my "if" statement doesn't exist. It skips right over the number 2.5 without running

if x == 2.5:
    print "X is now: ", x
    break

I figured it's something to do with the way my computer is running those numbers and the 2.5 i'm seeing is really 2.5000001 or something but I don't know. I've tried putting the numbers into scientific notation hoping it would help but instead I get the error "Too much output to process"

I'm fairly new to python and am starting to get annoyed by this. Any and all help it appreciated. Thanks.

Nolen Royalty
  • 18,415
  • 4
  • 40
  • 50
  • 1
    use `print(repr(x))` to see the (nearly) exact value of the float, and use `x =`[`decimal.Decimal()`](https://docs.python.org/2/library/decimal.html?highlight=decimal#decimal-objects) to prevent this from happening – Tadhg McDonald-Jensen Apr 11 '16 at 01:01

3 Answers3

1

When dealing with floating point mathematics it is often best to have some epsilon value to compare the data to for a threshold-ed comparison. For example

if abs( x - 2.5 ) < 0.001
    print  "X is now ", x
    break;
Lilith Daemon
  • 1,473
  • 1
  • 19
  • 37
  • Duplicate answer of http://stackoverflow.com/a/31111774/5827215. – Tadhg McDonald-Jensen Apr 11 '16 at 01:06
  • @TadhgMcDonald-Jensen Not really sure how it is a duplicate answer aside from the fact this is a basic ComSci method of solving floating point inaccuracies. – Lilith Daemon Apr 11 '16 at 01:10
  • sorry, not _duplicate_ per-say, but this method is already suggested to the question that this question is a duplicate to. – Tadhg McDonald-Jensen Apr 11 '16 at 01:13
  • @TadhgMcDonald-Jensen Ah, understandable. Honestly, I didn't even look at the duplicate question, as it was a relatively simple fix I just quickly typed up an answer to help solve the OP's problem. This is such a common (and easy if not always the best) method of comparing floating point values that I am sure there are likely hundreds if not thousands of answers that are almost identical on this site. – Lilith Daemon Apr 11 '16 at 01:18
  • Thanks Chris :) This solved my problem. Also, Tadhg, thanks for the link, I guess my googling skills are not as good as I thought they were. – Honey_Badger Apr 11 '16 at 01:25
0

The culprit is floating point math.

Floating Point Math:

Your language isn't broken, it's doing floating point math. Computers can only natively store integers, so they need some way of representing decimal numbers. This representation comes with some degree of inaccuracy. That's why, more often than not, .1 + .2 != .3. Why does this happen?

It's actually pretty simple. When you have a base 10 system (like ours), it can only express fractions that use a prime factor of the base. The prime factors of 10 are 2 and 5. So 1/2, 1/4, 1/5, 1/8, and 1/10 can all be expressed cleanly because the denominators all use prime factors of 10. In contrast, 1/3, 1/6, and 1/7 are all repeating decimals because their denominators use a prime factor of 3 or 7. In binary (or base 2), the only prime factor is 2. So you can only express fractions cleanly which only contain 2 as a prime factor. In binary, 1/2, 1/4, 1/8 would all be expressed cleanly as decimals. While, 1/5 or 1/10 would be repeating decimals. So 0.1 and 0.2 (1/10 and 1/5) while clean decimals in a base 10 system, are repeating decimals in the base 2 system the computer is operating in. When you do math on these repeating decimals, you end up with leftovers which carry over when you convert the computer's base 2 (binary) number into a more human readable base 10 number.

Source: http://0.30000000000000004.com/

Jason
  • 2,278
  • 2
  • 17
  • 25
0

As others have noted, the problem is the floating point math. For exact representation of small numbers, you might want to take a look at python's decimal module.

Miles
  • 100
  • 1
  • 10