The exact value of the float is 1.100000000000000088817841970012523233890533447265625
. Python isn't somehow keeping track of the original string. When Python stringifies it with str
, it truncates to 12 digits.
>>> x = 1.0/9
>>> print decimal.Decimal(x) # prints exact value
0.111111111111111104943205418749130330979824066162109375
>>> print x # truncated
0.111111111111
Even with repr
, Python uses the shortest string that will round to the original float when parsed with float
.
>>> print repr(x)
0.1111111111111111
If you want to parse JSON and get Decimal instances instead of float, you can pass a parse_float
argument to the load(s)
function:
>>> json.loads('{"foo": 1.234567890123456789}', parse_float=decimal.Decimal)
{u'foo': Decimal('1.234567890123456789')}
The above call causes decimal.Decimal
to be called to parse numbers in the JSON string, bypassing the rounding that would occur with intermediate float
or str
calls. You'll get exactly the number specified in the JSON.
Note that the API distinguishes between the functions used to parse things that look like floats, things that look like ints, and things that look like Infinity
, -Infinity
, or NaN
. This can be a bit inconvenient if you want all 3 categories to be handled the same way:
>>> json.loads('{"foo": 1.234567890123456789}',
... parse_float=decimal.Decimal,
... parse_int=decimal.Decimal,
... parse_constant=decimal.Decimal)
{u'foo': Decimal('1.234567890123456789')}