The answer to "what is the difference between str
and repr
" and even "what does full precision mean", depends on the Python version.
The behaviour of repr(f)
changed in 3.1 and 2.7.
Before 2.7 (including Python 3.0), repr(f)
would give up to 17 significant digits, as if formatted with %17g
. An IEEE-754 floating point value has 53 significant binary digits, which is approximately 16 decimal digits. 17 significant digits guarantee that each binary value produce a different decimal value.
In Pythons 2.7 and 3.1, the repr(f)
was made human-friendly while still keeping the precision:
The repr()
of a float
x
is shorter in many cases: it’s now based on the shortest decimal string that’s guaranteed to round back to x
. As in previous versions of Python, it’s guaranteed that float(repr(x))
recovers x
.
The behaviour of str(f)
was changed in Python 3.2:
The following examples demonstrate changes in repr
behaviour. The old behaviour was:
Python 2.6.8 (unknown, Jan 26 2013, 14:35:25)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.1415 * 2
6.2830000000000004
>>>
whereas the new behaviour is:
Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.1415 * 2
6.283
The old behaviour for str
(before Python 3.2) was to round values to 12 significant digits, losing information:
Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> str(0.1000000000000999)
'0.1'
>>> 0.1 == 0.1000000000000999
False
>>> repr(0.1000000000000999)
'0.1000000000000999'
The new behaviour since Python 3.2 is to behave like repr
:
Python 3.2.3 (default, Feb 20 2013, 14:44:27)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> str(0.1000000000000999)
'0.1000000000000999'
>>> repr(0.1000000000000999)
'0.1000000000000999'
The reason for why rounding will occur, is because floating point numbers in Python are represented as IEEE-754 double precision; one number takes 64 bits, with 1 bit reserved for sign, 10 for exponent and 53 for the mantissa (the actual numbers).
Many values, such as π or 1/3 cannot be accurately represented as an IEEE-754 binary floating point value. Even such a common number as 0.01 cannot be represented exactly.
The Python 3 float
s have the method hex()
that will convert the number to hex representation, which can be used to easily see the problem:
>>> (0.01).hex()
'0x1.47ae147ae147bp-7'
So, as hex, the number 0.01 would be approximated in binary as 1.47AE147AE147A4147AE... · 2-7; rounded to the closest number in 53 significant bits, this is represented as 1.47AE147AE147B · 2-7
I have written some more gory details on how repr
works in 2.7, 3.1 in my answer to question Precision of repr(f), str(f), print(f) when f is float.