[Python-ideas] Python Float Update

Steven D'Aprano steve at pearwood.info
Tue Jun 2 03:58:09 CEST 2015


On Tue, Jun 02, 2015 at 10:08:37AM +1000, Nick Coghlan wrote:

> It seems to me that a potentially better option might be to adjust the
> implicit float->Decimal conversion in the Decimal constructor to use
> the same algorithm as we now use for float.__repr__ [1], where we look
> for the shortest decimal representation that gives the same answer
> when rendered as a float. At the moment you have to indirect through
> str() or repr() to get that behaviour:

Apart from the questions of whether such a change would be allowed by 
the Decimal specification, and the breaking of backwards compatibility, 
I would really hate that change for another reason.

At the moment, a good, cheap way to find out what a binary float "really 
is" (in some sense) is to convert it to Decimal and see what you get:

Decimal(1.3) 
-> Decimal('1.3000000000000000444089209850062616169452667236328125')

If you want conversion from repr, then you can be explicit about it:

Decimal(repr(1.3))
-> Decimal('1.3')

("Explicit is better than implicit", as they say...)

Although in fairness I suppose that if this change happens, we could 
keep the old behaviour in the from_float method:

# hypothetical future behaviour
Decimal(1.3) 
-> Decimal('1.3')
Decimal.from_float(1.3) 
-> Decimal('1.3000000000000000444089209850062616169452667236328125')

But all things considered, I don't think we're doing people any favours 
by changing the behaviour of float->Decimal conversions to implicitly 
use the repr() instead of being exact. I expect this strategy is like 
trying to flatten a bubble under wallpaper: all you can do is push the 
gotchas and surprises to somewhere else.

Oh, another thought... Decimals could gain yet another conversion 
method, one which implicitly uses the float repr, but signals if it was 
an inexact conversion or not. Explicitly calling repr can never signal, 
since the conversion occurs outside of the Decimal constructor and 
Decimal sees only the string:

Decimal(repr(1.3)) cannot signal Inexact.

But:

Decimal.from_nearest_float(1.5)  # exact
Decimal.from_nearest_float(1.3)  # signals Inexact

That might be useful, but probably not to beginners.


-- 
Steve


More information about the Python-ideas mailing list