0

I'm learning Python and have been trying various things... for some reason this isn't working!

x = (-2.1)

if ( (0.4*(x)) - (0.02*(x)) + (1.396) ) == 0.598:
    print "TRUE!"
else:
    print "FALSE!"
    print ( (0.4*(x)) - (0.02*(x)) + (1.396) )

It prints FALSE! Followed by 0.598. Obviously the answer is 0.598, so why doesn’t the "if" statement work?

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt Yaple
  • 65
  • 1
  • 8
  • 1
    Floating point numbers are not that precise, you need to apply some heuristics on how close you want your numbers to be. – Martijn Pieters Jan 07 '14 at 20:13
  • Or more in general: floats arithmetics is not the same as arithmetics on real numbers. Float addition and multiplication are not distributive, etc, etc. – Hyperboreus Jan 07 '14 at 20:14
  • That's interesting... how would I fix it? – Matt Yaple Jan 07 '14 at 20:14
  • `2.1` is not 2.1, it is 2.100000000000000088817841970012523233890533447265625. Same for all the other values in your code. Print them, and the intermediate results, to full precision and you may see that each time the best representable approximation for the value being computed was chosen. – Pascal Cuoq Jan 07 '14 at 20:15
  • You're writing Python, not Lisp. Lay off the parens a bit. – Wooble Jan 07 '14 at 20:15
  • To illustrate, try `print format(0.598, '.53f')` to see that Python has approximated the value. – Martijn Pieters Jan 07 '14 at 20:15
  • @MattYaple Define some `e` as a boundary and test for `abs(expected - actual) <= e`. – Hyperboreus Jan 07 '14 at 20:15
  • 1
    @Hyperboreus Floating-point addition is definitely commutative. – Pascal Cuoq Jan 07 '14 at 20:15
  • @PascalCuoq What thou hast said is just and right. I deleted this part. – Hyperboreus Jan 07 '14 at 20:16
  • @PascalCuoq I was thinking about associativity. Is floating point addition associative? – Hyperboreus Jan 07 '14 at 20:18
  • @Hyperboreus sure not. think about overflows – alko Jan 07 '14 at 20:18
  • @MattYaple One way is to use the Decimal system: http://docs.python.org/2/library/decimal.html arithmetic using Decimal objects is slower, but precise in the sense that you probably want it to be. – Andrew Gorcester Jan 07 '14 at 20:18
  • 3
    I have to say I disagree with all of the downvotes on this question. It is a coherent, specific question with proper code and output examples. Yes, the question has been asked before, but unfortunately the nature of this problem is that you don't know what terminology to use to search for the question until you know the answer. – Andrew Gorcester Jan 07 '14 at 20:20
  • @AndrewGorcester moreover, I think question is more related to printing floats functionality, but not to float precision. – alko Jan 07 '14 at 20:21
  • @Hyperboreus As alko said, there is overflow: `FLT_MAX + FLT_MAX + (-FLT_MAX)` depends which addition you do first (FLT_MAX is probably called something else in Python). Examples do not need overflow: `1e100 + (-1e100) + 1` also depends on operations order. But when the result of an addition (or subtraction) falls in a binade that is as close to zero as the binade of both arguments, then it is automatically exact. Also `x + x` is always exact if it does not overflow. There are many properties that one can use to take advantage of floating-point beyond “it is not exact”. – Pascal Cuoq Jan 07 '14 at 20:38
  • @Matt Yaple When things don't work like how they're supposed,as an advice write print statements and understand what's happening.Using `print` for debugging is the best advice anyone will give in Python. – Andy_A̷n̷d̷y̷ Jan 07 '14 at 20:57
  • 1
    @Andy That is what was confusing to me. It was supposed to print true if it equalled .598, but it printed false. So I decided to print the answer to the equation... and it printed .598! I now understand it only prints the rounded answer... not .59800000000004132413251 or whatever it actually is – Matt Yaple Jan 08 '14 at 20:50

2 Answers2

2

If you try to print out

(0.38 * x) + 1.396 # note simplified maths and syntax

You will quickly see why:

0.5979999999999999

This is not exactly equal to 0.598, because of the way floating point numbers (float) work. You are better testing these using tolerance:

a = (0.38 * x) + 1.396

if abs(a - 0.598) < 0.0001:
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
1

You're confused because Python print is using float.__str__, which in turn trims up to 12 digits, so numbers are not what is printed:

>>> ( (0.4*(x)) - (0.02*(x)) + (1.396) ).__str__()
'0.598'
>>> ( (0.4*(x)) - (0.02*(x)) + (1.396) ).__repr__()
'0.5979999999999999'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alko
  • 46,136
  • 12
  • 94
  • 102