[Python-ideas] numerical type combining integer and float/decimal properties [Was: Re: Python Numbers as Human Concept Decimal System]
Wolfgang Maier
wolfgang.maier at biologie.uni-freiburg.de
Mon Mar 10 18:48:21 CET 2014
Am Montag, 10. März 2014 14:53:42 UTC+1 schrieb Stefan Krah:
> [My apologies for being terse, I don't have much time to follow this
discussion right now.]
> Nick Coghlan <ncoghlan at gmail.com> wrote:
>> I think users of decimal literals will just need to deal with the risk of
unexpected rounding, as the alternatives are even more problematic.
> That is why I think we should seriously consider moving to IEEE semantics
for a decimal literal. Among other things:
> - Always round the literal inputs.
> - Supply IEEE contexts.
> - Make Decimal64 the default.
> - Add the missing rounding modes to sqrt() and exp().
> - Keep the ability to create exact Decimals through the constructor when
no context is passed.
> - Make the Decimal constructor use the context for rounding if it is passed.
> - ...
While I find this discussion about decimal literals extremely interesting,
in my opinion, such a literal should have an underlying completely new
numerical type, if it is really supposed to be for inexperienced users.
Most of the discussions right now concern rounding issues that occur after
the decimal point, but I think an at least equally big problem is rounding
*to the left* of it as in (using current float):
>>> 1e50 + 1000
1e+50
Importantly, Decimal is no cure here:
>>> Decimal(10**50) + Decimal(100)
Decimal('1.000000000000000000000000000E+50')
(of course, you can debate context settings to make this particular example
work, but, in general, it happens with big enough numbers.)
The solution for this example is using ints of course:
>>> 10**50 + 100
100000000000000000000000000000000000000000000000100
, but obviously this works only for whole numbers, so there currently is no
built-in way to make this example work correctly:
>>> 10**50 - 9999999999999999.5
1e+50
(or with Decimal:
>>> Decimal(10**50) - Decimal('9999999999999999.5')
Decimal('1.000000000000000000000000000E+50')
).
If we are discussing a new number literal I would like to have it cope with
this and my suggestion is a new numeric type that's sort of a hybrid between
int and either Decimal or float, i.e., a type that behaves like int for
digits left of the decimal point, but may truncate to the right.
In pure Python, something similar (but not a literal form of course) could
be implemented as a class that stores the left digits as an int and the
right digits as a float/Decimal internally. Calculations involving this
class would be slow due to the constant need of shifting digits between the
integer´and the float part, and might be too slow for many users even when
written in C, but its behavior would meet the expectation of inexperienced
people better than the existing types.
Going back to Mark Harris' initial proposal of unifying numeric types (which
I am not trying to support in any way here), such a type would even allow to
unify int and float since an ints could be considered a subset of the new
type with a fractional part of zero.
Cheers,
Wolfgang
More information about the Python-ideas
mailing list