prePEP: Decimal data type

John Roth newsgroups at jhrothjr.com
Sat Nov 1 10:15:43 EST 2003


Lots of comments in line. See especially the comment
about *NOT* wanting limited precision, as envisioned
in the referenced decimal *floating point* standards.

John Roth


"Batista, Facundo" <FBatista at uniFON.com.ar> wrote in message
news:mailman.295.1067625441.702.python-list at python.org...
> Here I send it.
>
> Suggestions and all kinds of recomendations are more than welcomed.
>
> If it all goes ok, it'll be a PEP when I finish writing/modifying the
code.
>
> Thank you.
>
> . Facundo
>
>
> ------------------------------------------------------------------------
>
> PEP: XXXX
> Title: Decimal data type
> Version: $Revision: 0.1 $
> Last-Modified: $Date: 2003/10/31 15:25:00 $
> Author: Facundo Batista <fbatista at unifon.com.ar>
> Status: Draft
> Type: Standards Track
> Content-Type: text/x-rst
> Created: 17-Oct-2003
> Python-Version: 2.3.3
>
>
> Abstract
> ========
>
> The idea is to have a Decimal data type, for every use where decimals are
> needed but floating point is too inexact.
>
> The Decimal data type should support the Python standard functions and
> operations and must comply the decimal arithmetic ANSI standard
X3.274-1996.

Why is ANSI 274 significant? The reason I ask this is that this is
a ***floating point*** standard, and I don't think that we particularly
care for decimal floating point.

Floating point presumes limited precision. In other words, if the actual
number (exclusive of the location of the decimal point) gets too large,
the least significant part is ... thrown away. I don't want that.

Since we've got infinite precision integer arithmetic, going to
limited precision decimal arithmetic is, IMNSHO, a step backwards.


>
> Rationale
> =========
>
> I must separate the requeriments in two sections.  The first is to comply
> with the ANSI standard.  All the needings for this are specified in the
> Mike Cowlishaw's work at http://www2.hursley.ibm.com/decimal/.
Cowlishaw's
> also provided a **lot** of test cases.  The second section of requeriments
> (standard Python functions support, usability, etc) are detailed in the
> `Requirements`_ section.
>
> Here I'll include all the decisions made and why, and all the subjects
still
> being discussed.  The requirements will be numbered, to simplify
discussion
> on each point.
>
> This work is based on code and test functions written by Eric Price, Aahz
> and Tim Peters.  Actually I'll work on the Decimal.py code in the sandbox
(at
> python/nondist/sandbox/decimal in SourceForge).  Some of the explanations
of
> this PEP are taken from the Cowlishaw's work.
>
>
> Items In Discussion
> -------------------
>
> When in a case like ``Decimal op otherType`` (see point 12 in
Requirements_
> for details), what should happen?
>
>     if otherType is an int or long:
>
>         a. an exception is raised
>         b. otherType is converted to Decimal
>         c. Decimal is converted to int or long (with ``int()`` or
> ``long()``)
>
>     if otherType is a float:
>
>         d. an exception is raised
>         e. otherType is converted to Decimal (rounding? see next item in
>            discussion)
>         f. Decimal is converted to float (with ``float()``)
>
>     if otherType is a string:
>
>         g. an exception is raised
>         h. otherType is converted to Decimal
>         i. Decimal is converted to string (bizarre, huh?)

The "other type" should be handled in the same way the decimal()
constructor would handle it.


> When passing floating point to the constructor, what should happen?
>
>     j. ``Decimal(1.1) == Decimal('1.1')``
>     k. ``Decimal(1.1) ==
> Decimal('110000000000000008881784197001252...e-51')``

Clearly, j is the correct answer. It's not all that hard to do, either.

>
>
> Requirements
> ============
>
> 1. The syntax should be ``Decimal(value)``.

Lower case: "decimal(value, [scale factor])"

> 2. The value could be of the type:
>
>        - another Decimal
>        - int or long
>        - float
>        - string

OK.

> 3. To exist a Context.  The context represents the user-selectable
> parameters
>    and rules which govern the results of arithmetic operations.  In the
>    context the user defines:
>
>        - what will happen with the exceptional conditions.
>        - what precision will be used
>        - what rounding method will be used

See my general comment above with respect to precision. We should
not implement limited precision. Likewise, there is no reason to have
exceptional conditions in the sense of the IEEE floating point standard.

> 4. The Context must be omnipresent, meaning that changes to it affects all
>    the current and future Decimal instances.

No. The context should be selectable for the particular usage. That is,
it should be possible to have several different contexts in play at one
time in an application.

>
> 5. The exceptional conditions should be grouped into signals, which could
be
>    controlled individually.  The context should contain a flag and a
>    trap-enabler for each signal.  The signals should be: clamped,
>    division-by-zero, inexact, invalid-operation, overflow, rounded,
> subnormal
>    and underflow.

See my general comment on limited precision arithmetic. This eliminates
all of the possible exceptional conditions except division-by-zero and
inexact (which is only possible for division and sqrt.) Division by zero
should always be handled by an exception; square root needs its own
specification.

> 6. For each of the signals, the corresponding flag should be set to 1 when
>    the signal occurs.  It is only reset to 0 by explicit user action.

Since I've just eliminated the signals, this vanishes.

>
> 7. For each of the signals, the corresponding trap-enabler will indicate
>    which action is to be taken when the signal occurs.  If 0, a defined
>    result should be supplied, and execution should continue.  If 1, the
>    execution of the operation should end and an exception should be
raised.

Likewise.

> 8. The precision (maximum number of significant digits that can result
from
>    an arithmetic operation) must be positive (greater than 0).

See my general comment on the undesirability of limited precision
arithmetic.


> 9. To have different kinds of rounding; you can choose the algorithm
through
>    context:
>
>        - ``round-down``: (Round toward 0, truncate) The discarded digits
are
>          ignored; the result is unchanged::
>
>              1.123 --> 1.12
>              1.128 --> 1.12
>              1.125 --> 1.12
>              1.135 --> 1.13
>
>        - ``round-half-up``: If the discarded digits represent greater than
> or
>          equal to half (0.5) then the result should be incremented by 1
>          (rounded up); otherwise the discarded digits are ignored::
>
>              1.123 --> 1.12
>              1.128 --> 1.13
>              1.125 --> 1.13
>              1.135 --> 1.14
>
>        - ``round-half-even``: If the discarded digits represent greater
than
>          half (0.5) then the result coefficient should be incremented by 1
>          (rounded up); if they represent less than half, then the result
is
>          not adjusted (that is, the discarded digits are ignored);
otherwise
>          the result is unaltered if its rightmost digit is even, or
>          incremented by 1 (rounded up) if its rightmost digit is odd (to
> make
>          an even digit)::
>
>              1.123 --> 1.12
>              1.128 --> 1.13
>              1.125 --> 1.12
>              1.135 --> 1.14
>
>        - ``round-ceiling``: If all of the discarded digits are zero or if
> the
>          sign is negative the result is unchanged; otherwise, the result
>          should be incremented by 1 (rounded up)::
>
>              1.123 --> 1.13
>              1.128 --> 1.13
>              -1.123 --> -1.12
>              -1.128 --> -1.12
>
>        - ``round-floor``: If all of the discarded digits are zero or if
the
>          sign is positive the result is unchanged; otherwise, the absolute
>          value of the result should be incremented by 1::
>
>              1.123 --> 1.12
>              1.128 --> 1.12
>              -1.123 --> -1.13
>              -1.128 --> -1.13
>
>        - ``round-half-down``: If the discarded digits represent greater
than
>          half (0.5) then the result should be incremented by 1 (rounded
up);
>          otherwise the discarded digits are ignored::
>
>              1.123 --> 1.12
>              1.128 --> 1.13
>              1.125 --> 1.12
>              1.135 --> 1.13
>
>        - ``round-up``: (Round away from 0) If all of the discarded digits
> are
>          zero the result is unchanged. Otherwise, the result should be
>          incremented by 1 (rounded up)::
>
>              1.123 --> 1.13
>              1.128 --> 1.13
>              1.125 --> 1.13
>              1.135 --> 1.14

I think this is simply too much. I'd rather have a round() method that
takes a *small* number of standard options, and otherwise takes a
function to do the rounding.

>
> 10. Strings with floats in engineering notation will be supported.

OK.

>
> 11. Calling repr() should do round trip, meaning that::
>
>        m = Decimal(...)
>        m == eval(repr(m))

OK.


> 12. To support the basic aritmetic (``+, -, *, /, //, **, %, divmod``) and
>     comparison (``==, !=, <, >, <=, >=, cmp``) operators in the following
>     cases:
>
>        - Decimal op Decimal
>        - Decimal op otherType
>        - otherType op Decimal
>        - Decimal op= Decimal
>        - Decimal op= otherType
>
>     Check `Items In Discussion`_ to see what types could OtherType be, and
>     what happens in each case.



> 13. To support unary operators (``-, +, abs``).

OK.
>
> 14. To support the built-in methods:
>
>         - min, max
>         - float, int, long
>         - str, repr
>         - hash
>         - copy, deepcopy
>         - bool (0 is false, otherwise true)

OK, although I note that sqrt() isn't included, which makes
the discussion of "inexact" earlier moot.
>
> 15. To be immutable.

OK.
>
>
> Reference Implementation
> ========================
>
> To be included later:
>
>     - code
>     - test code
>     - documentation
>
>
> Copyright
> =========
>
> This document has been placed in the public domain.
>






More information about the Python-list mailing list