On Thu, Aug 8, 2019 at 11:50 PM Rhodri James <[email protected]> wrote:
>
> On 08/08/2019 11:22, Richard Musil wrote:
> > I have found myself in an awkward situation with current (Python 3.7) JSON 
> > module. Basically it boils down to how it handles floats. I had been hit on 
> > this particular case:
> >
> > In [31]: float(0.6441726684570313)
> > Out[31]: 0.6441726684570312
> >
> > but I guess it really does not matter.
>
> Well, yes it does.  It's pretty much the whole of the matter.  Unless
> you get lucky with values, floats are inherently imprecise.  The number
> you are playing with is apparently 0.64417266845703125 as an IEEE float
> representation.  It happens that Python rounds down ("rounds to even" is
> the statement in the documentation) when it displays this.
>
> Essentially you are not getting the precision you think you are getting.
>

Floats are actually rational numbers subject to a few constraints,
including that the denominator be a power of two. For display, Python
happens to choose some number which is represented identically to the
original value (and, I believe, picks the one with the shortest
decimal representation). Floats aren't "inherently imprecise"; they
have a specific finite precision that is defined in binary, and then
there are multiple equivalently valid decimal numbers that all will
encode to the same bits.

So yes, if you think you are getting a certain number of *decimal*
digits of precision, then you're not - you're getting both more and
less precision than that. You're getting a certain number of *binary*
digits. In fact, the number given above can be shown to be this
fraction:

>>> "%d/%d" % 0.6441726684570313.as_integer_ratio()
'84433/131072'

Which is the number ending ...03125. Effectively, the number ...0313
is being rounded down to ...03125; yes, it's being rounded to a number
that requires MORE decimal digits to display it. Since the display is
being shown to a limited number of decimal digits, the stored value
has to be rounded, and that results in something that isn't identical
to the input. But both ...0313 and ...0312 get rounded to ...03125 for
storage, so they are equally valid representations of the
floating-point value 84433/131072.

ChrisA
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/ALL3MORTXUXCSTTY6CJKLS5EGFV5SO67/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to