UPDATE: In Python 3 str
on a float is guaranteed to produce a string literal with full precision
This was not the case in Python 2. For instance str(1.0000000000000002)
was '1.0'
in Python 2, but in Python 3 it gives '1.0000000000000002'
as expected.
This has often been a source of confusion because a simply print(x)
may not have printed x
with the full precision, making wrong conclusions -- like in the example of the question.
For the background of this change see here.
Python 2 solution
A simple solution to get a string representation of a float with full precision is to use either repr
or json.dumps
.
JSON serialization/deserialization has to make sure that roundtrips are loss-less, and thus, the implementation produces a string representation you are looking for:
def check(x, y):
print(repr(x))
print(repr(y))
print("x == y is {}".format(x == y))
In [1]: check(1.00000000000000001, 1.0000000000000002)
1.0
1.0000000000000002
x == y is False
In [2]: check(1e-300, 2e-300)
1e-300
2e-300
x == y is False
In [3]: check(1e+300, 2e+300)
1e+300
2e+300
x == y is False
This also clarifies that 1.00000000000000001
actually is 1.0. This can also be checked by enumerating the numbers around 1.0 using np.nextafter
, which produces the next larger/smaller representable floating point value:
0.9999999999999994
0.9999999999999996
0.9999999999999997
0.9999999999999998
0.9999999999999999
[*] 1.0
1.0000000000000002
1.0000000000000004
1.0000000000000007
1.0000000000000009
1.000000000000001
In reply to @Robert:
json.dumps
also works in your case. The formatting with '.60g'
simply produces a literal that has more unnecessary digits than a IEEE double precision number can hold. The precision of the other literal produced by json.dumps
is sufficient to represent that particular floating point number, which you can check by:

The two IEEE literals closest to 1./math.sqrt(3.)
are:

The first one the closest possible representation already, storing further digits of 1./math.sqrt(3.)
will always give you back that same number.
json.dumps
has loss-less round-trips for 64-bit IEEE floating point numbers, so it is guaranteed that the number of digits it produces is sufficient.