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 -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/LGVKOQR6CXOHDXD32Q3WA55LRZN7QZ7D/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to