On Thu, Mar 05, 2020 at 12:39:38PM +0000, Steve Barnes wrote:
> Hmm, is there a PEP regarding Decimal literals?
No.
> I couldn't find one,
> although there is PEP 240 regarding rational literals. Maybe it's time
> to write up a rejected PEP explaining exactly what the problems are
> with Decimal literals.
The proposal hasn't been rejected, it just faded away for lack of
somebody to write the PEP and offer to do the work.
As I recall, a number of senior core developers were tentatively
interested in the idea, at least in principle. Nick Coghlan was one, if
memory serves me right. I don't recall any major objections, although
that part might be confirmation bias :-)
> From memory, the problems are (a) it'd
> effectively require the gigantic decimal module to be imported by
> default, and (b) contexts don't work with literals.
Neither of those are problems. They are only problems if you expect the
(hypothetical) builtin decimal type to be the exact decimal.Decimal
type, but that is overkill for the use-cases for a builtin decimals.
All the context related functionality would be dropped: builtin.decimal
would implement only a fixed width with a single rounding mode. They
would be effectively like float, only base 10.
For those who need the extra functionality of decimal.Decimal, the
module would still exist. But builtins.decimal would be aimed at the
simpler use-case of numerically unsophisticated users who wouldn't know
a rounding mode or trap if it bit them but do know that 0.1 + 0.2 should
equal 0.3 :-)
There are a couple of standards for fixed-width decimals, by memory we
were considering either 64 bit or 128 bit decimals.
> I think that a part of the problem is that because Decimal silently
> accepts both float and string literal inputs things get surprising
> e.g.:
>
> In [5]: D(0.3) == D('0.3')
> Out[5]: False
That's only surprising to those who don't read the docs :-)
> 1. Deprecate the use of the Decimal initialiser with float inputs so
> that decimal.Decimal(0.1), etc., issues a warning
[...]
> 3. Eventually outlaw float as an input to the initialiser.
Please no. We started there, and relaxed that restriction because it was
more annoying than helpful. Going backwards to Python 2.5 or thereabouts
is, well, going backwards:
>>> decimal.Decimal(0.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.5/decimal.py", line 648,
in __new__ "First convert the float to a string")
TypeError: Cannot convert float to Decimal. First convert
the float to a string
Numerically unsophisticated users are not the only users of Decimal, and
frankly, the unsophisticated users aren't going to be any less surprised
by Decimal(0.1) raising an exception than they are surprised by any of
the other floating-point oddities that affect both decimal and float.
> While this would "break" code which happen to work as expected, e.g.
> decimal.Decimal(0.5) but at least we would have consistent behaviour
> and fail early rather than potentially working but giving incorrect or
> inconsistent results.
It's not giving incorrect results. It is giving correct results. The
problem is not Decimal, but that people think that 0.1 means one tenth
when it actually means 3602879701896397 ÷ 36028797018963968 :-)
Viewing Decimal(0.1) is an excellent way to discover what value 0.1
actually has, as opposed to the value you think it has.
--
Steven
_______________________________________________
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/LGVKOQR6CXOHDXD32Q3WA55LRZN7QZ7D/
Code of Conduct: http://python.org/psf/codeofconduct/