3

So I break out the Python 2.6 interpreter and I get this:

Python 2.6.6 (r266:84292, Nov 22 2013, 12:16:22) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 2.1
2.1000000000000001
>>> 2.2
2.2000000000000002
>>> 2.2
2.2000000000000002

However in Python 2.7 I get more human-like results like below:

Python 2.7.5+ (default, Sep 19 2013, 13:48:49) 
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 5.4
5.4
>>> 1.1
1.1
>>> 0.2
0.2
>>> 

I 'd like to ask why is this happening and how could I possibly make Python 2.6 behave like 2.7?

stratis
  • 7,750
  • 13
  • 53
  • 94
  • 7
    Are you aware that 2.7 is just lying to you, and not actually more accurate? – Wooble Dec 17 '13 at 19:53
  • 1
    @Wooble: It's true that 2.7 is not more accurate, but 2.6 and 2.7 are both lying. Pretty much anything that uses binary floating point is lying, in the sense you're talking about. (And 2.7 actually does *round* more accurately than 2.6, as defined by the IEEE spec.) – John Y Dec 17 '13 at 20:15

1 Answers1

10

The float.__repr__() and float.__str__() methods in Python 2.7 changed; the Python 3.1 float-to-string conversion method was backported and values are now rounded.

The C source code for float.__str__() formats a floating point value using the g formatter code to the sprintf() function, with a precision of 12 positions.

To get the same result in Python 2.6, you'll have to format the string yourself:

'%.12g' % fp_value

or use the format() function:

format(fp_value, '.12g')

Note that in Python 2.7 only the representation changed, not the actual values. Floating point values are still binary approximations of real numbers, and binary fractions don't always add up to the exact number represented.

If you need to have more precision than what float approximations offer you, you need to switch to using the decimal.Decimal() type instead. This maintains precision, at the cost of speed (floating point arithmetic is handled in hardware on modern computers).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks! I just need a precision of 2 positions and not 12. In Python 2.6.. (representation-wise as you said) – stratis Dec 17 '13 at 20:24
  • @Konos5: the value will be rounded to at most 12 digits; try it out. – Martijn Pieters Dec 17 '13 at 20:26
  • True. It works..! However the result in a string. Any ideas on how I could turn that back to a (twisted sense of) proper float..? – stratis Dec 17 '13 at 20:34
  • 1
    @Konos5: You cannot. That's not what a floating point value **is**. The values in Python 2.6 and 2.7 haven't changed, only their string *representation*. You are misunderstanding how floating point values *work*. – Martijn Pieters Dec 17 '13 at 20:37
  • @Konos5: This is what Wooble and John Y are referring to in their comments. – Martijn Pieters Dec 17 '13 at 20:37
  • 1
    @Konos5: Try this: `format(fp, '.53f')` in both Python 2.6 and 2.7, to print a floating point value with maximum decimals, and you'll see that *both* are still approximations. – Martijn Pieters Dec 17 '13 at 20:38
  • I think I get your point. The number hasn't changed. Just its representation which btw can be manipulated through the format function..! If only the format function would return 'pseudo'-floats.. – stratis Dec 17 '13 at 20:40
  • @Konos5: you may want the decimal module if you want actual numbers with only 2 digits of precision. – Wooble Dec 18 '13 at 12:16