prePEP: Decimal data type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Batista, Facundo

    prePEP: Decimal data type

    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@unifo n.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.


    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?)


    When passing floating point to the constructor, what should happen?

    j. ``Decimal(1.1) == Decimal('1.1')` `
    k. ``Decimal(1.1) ==
    Decimal('110000 000000000008881 784197001252... e-51')``


    Requirements
    ============

    1. The syntax should be ``Decimal(value )``.

    2. The value could be of the type:

    - another Decimal
    - int or long
    - float
    - string

    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

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

    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.

    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.

    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.

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

    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

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

    11. Calling repr() should do round trip, meaning that::

    m = Decimal(...)
    m == eval(repr(m))

    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``).

    14. To support the built-in methods:

    - min, max
    - float, int, long
    - str, repr
    - hash
    - copy, deepcopy
    - bool (0 is false, otherwise true)

    15. To be immutable.


    Reference Implementation
    =============== =========

    To be included later:

    - code
    - test code
    - documentation


    Copyright
    =========

    This document has been placed in the public domain.

  • Emile van Sebille

    #2
    Re: prePEP: Decimal data type


    "Batista, Facundo" <FBatista@uniFO N.com.ar> wrote in message
    news:mailman.29 5.1067625441.70 2.python-list@python.org ...[color=blue]
    > Here I send it.
    >
    > Suggestions and all kinds of recomendations are more than welcomed.
    >[/color]

    [snip]
    [color=blue]
    > Items In Discussion
    > -------------------
    >
    > When in a case like ``Decimal op otherType`` (see point 12 in[/color]
    Requirements_[color=blue]
    > 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()``)
    >[/color]

    Wouldn't you want the result to return a Decimal? eg:

    price = Decimal(3.15)
    qty = 3
    extension = qty * price

    extension should now be a Decimal instance.

    In that case, it looks like (b.) wins by default, as (a.) is clearly not
    what you'd want; and (c.) yields potential results that give rise to needing
    Decimal in the first place. I'd expect anything functionally less than the
    above pseudo-snippet to be cumbersome to use.

    [color=blue]
    > 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()``)
    >[/color]

    retail = Decimal(3.15)
    discount = 35
    wholesale = retail * (100-discount)/100

    Here again, if the choices are limited to one of d|e|f then e seems the
    best.
    [color=blue]
    > if otherType is a string:
    >
    > g. an exception is raised
    > h. otherType is converted to Decimal
    > i. Decimal is converted to string (bizarre, huh?)
    >[/color]

    (g.) - I can't think of a use case where you'd want a known Decimal to work
    with a string.

    [color=blue]
    >
    > When passing floating point to the constructor, what should happen?
    >
    > j. ``Decimal(1.1) == Decimal('1.1')` `
    > k. ``Decimal(1.1) ==
    > Decimal('110000 000000000008881 784197001252... e-51')``
    >[/color]

    Well, persistence will bring in a whole set of problems. (j.) is, of
    course, what I'd want.

    [snip]
    [color=blue]
    > 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
    >
    > 4. The Context must be omnipresent, meaning that changes to it affects all
    > the current and future Decimal instances.[/color]

    Does this imply then that there is unlimited precision being maintained
    under the covers?


    Emile van Sebille
    emile@fenx.com



    Comment

    • John Roth

      #3
      Re: prePEP: Decimal data type

      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@uniFO N.com.ar> wrote in message
      news:mailman.29 5.1067625441.70 2.python-list@python.org ...[color=blue]
      > 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[/color]
      code.[color=blue]
      >
      > 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@unifo n.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[/color]
      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.

      [color=blue]
      >
      > 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/.[/color]
      Cowlishaw's[color=blue]
      > 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[/color]
      still[color=blue]
      > being discussed. The requirements will be numbered, to simplify[/color]
      discussion[color=blue]
      > 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[/color]
      (at[color=blue]
      > python/nondist/sandbox/decimal in SourceForge). Some of the explanations[/color]
      of[color=blue]
      > this PEP are taken from the Cowlishaw's work.
      >
      >
      > Items In Discussion
      > -------------------
      >
      > When in a case like ``Decimal op otherType`` (see point 12 in[/color]
      Requirements_[color=blue]
      > 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?)[/color]

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

      [color=blue]
      > When passing floating point to the constructor, what should happen?
      >
      > j. ``Decimal(1.1) == Decimal('1.1')` `
      > k. ``Decimal(1.1) ==
      > Decimal('110000 000000000008881 784197001252... e-51')``[/color]

      Clearly, j is the correct answer. It's not all that hard to do, either.
      [color=blue]
      >
      >
      > Requirements
      > ============
      >
      > 1. The syntax should be ``Decimal(value )``.[/color]

      Lower case: "decimal(va lue, [scale factor])"
      [color=blue]
      > 2. The value could be of the type:
      >
      > - another Decimal
      > - int or long
      > - float
      > - string[/color]

      OK.
      [color=blue]
      > 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[/color]

      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.
      [color=blue]
      > 4. The Context must be omnipresent, meaning that changes to it affects all
      > the current and future Decimal instances.[/color]

      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.
      [color=blue]
      >
      > 5. The exceptional conditions should be grouped into signals, which could[/color]
      be[color=blue]
      > 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.[/color]

      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.
      [color=blue]
      > 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.[/color]

      Since I've just eliminated the signals, this vanishes.
      [color=blue]
      >
      > 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[/color]
      raised.

      Likewise.
      [color=blue]
      > 8. The precision (maximum number of significant digits that can result[/color]
      from[color=blue]
      > an arithmetic operation) must be positive (greater than 0).[/color]

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

      [color=blue]
      > 9. To have different kinds of rounding; you can choose the algorithm[/color]
      through[color=blue]
      > context:
      >
      > - ``round-down``: (Round toward 0, truncate) The discarded digits[/color]
      are[color=blue]
      > 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[/color]
      than[color=blue]
      > half (0.5) then the result coefficient should be incremented by 1
      > (rounded up); if they represent less than half, then the result[/color]
      is[color=blue]
      > not adjusted (that is, the discarded digits are ignored);[/color]
      otherwise[color=blue]
      > 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[/color]
      the[color=blue]
      > 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[/color]
      than[color=blue]
      > half (0.5) then the result should be incremented by 1 (rounded[/color]
      up);[color=blue]
      > 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[/color]

      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.
      [color=blue]
      >
      > 10. Strings with floats in engineering notation will be supported.[/color]

      OK.
      [color=blue]
      >
      > 11. Calling repr() should do round trip, meaning that::
      >
      > m = Decimal(...)
      > m == eval(repr(m))[/color]

      OK.

      [color=blue]
      > 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.[/color]


      [color=blue]
      > 13. To support unary operators (``-, +, abs``).[/color]

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

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

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


      Comment

      • Alex Martelli

        #4
        Re: prePEP: Decimal data type

        John Roth wrote:
        [color=blue]
        > Lots of comments in line. See especially the comment
        > about *NOT* wanting limited precision, as envisioned
        > in the referenced decimal *floating point* standards.[/color]
        ...[color=blue]
        > Since we've got infinite precision integer arithmetic, going to
        > limited precision decimal arithmetic is, IMNSHO, a step backwards.[/color]

        There may be a niche for a Rational data type, but in MHO it cannot take the
        place of a limited-precision-decimal (fixed or float). I suggest you think
        of a separate PEP to propose Rational (check the existing and rejected ones
        first, there may be some that are relevant) rather than attacking this one.

        I think Guido will never accept rationals becoming as widespread as they
        were in ABC (the default noninteger type) and is on record as saying that.
        The performance implications of the fact that summing two rationals (which
        take O(M) and O(N) space respectively) gives a rational which takes O(M+N)
        memory space is just too troublesome. There are excellent Rational
        implementations in both pure Python and as extensions (e.g., gmpy), but
        they'll always be a "niche market" IMHO. Probably worth PEPping, not worth
        doing without Decimal -- which is the right way to represent sums of money,
        a truly major use case in the real world.

        (Facundo, I think you should include these considerations in the PEP to
        explain why you're NOT going for rationals.)

        [color=blue][color=green]
        >> if otherType is a string:
        >>
        >> g. an exception is raised
        >> h. otherType is converted to Decimal
        >> i. Decimal is converted to string (bizarre, huh?)[/color]
        >
        > The "other type" should be handled in the same way the decimal()
        > constructor would handle it.[/color]

        I think this total breach with Python tradition would be a terrible mistake.

        23+"43" is NOT handled in the same way as 23+int("45"), and a VERY
        good thing that is too. It's a completely different thing for a user to
        EXPLICITLY indicate they want construction (conversion) and to just happen
        to sum two objects one of which by mistake could be a string.

        (Facundo, perhaps it's worth it for the PEP to point this out explicitly,
        too; part of a PEP's purpose is to record the highlights of the discussion
        and design choices that had to be made).


        Alex

        Comment

        • Paul Moore

          #5
          Re: prePEP: Decimal data type

          "John Roth" <newsgroups@jhr othjr.com> writes:
          [color=blue][color=green]
          >> 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.[/color]
          >
          > 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.[/color]

          To be honest, I have little if any practical experience with numeric
          representation issues, but it seems sensible to me to implement a
          pre-existing, and presumably well thought out, standard, rather than
          inventing something ad-hoc.

          Of course, if the need is for something other than what ANSI 274
          standardises, which seems to be what you are implying, then fair
          enough. But what do you require? Infinite-precision decimal
          arithmetic? If so, can you explain how you'd handle something like
          1/3?

          (I'm not being deliberately awkward here - my impression is that
          representation issues are *hard*, and there are a lot of traps you can
          fall into by oversimplifying . That's why I prefer the idea of a
          pre-existing standard: it implies that *someone* has thought about the
          hard stuff).
          [color=blue]
          > 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.[/color]

          Even infinite precision integers throw away information, in some
          sense. Witness:
          [color=blue][color=green][color=darkred]
          >>> 1L//3L[/color][/color][/color]
          0L
          [color=blue][color=green]
          >> When passing floating point to the constructor, what should happen?
          >>
          >> j. ``Decimal(1.1) == Decimal('1.1')` `
          >> k. ``Decimal(1.1) ==
          >> Decimal('110000 000000000008881 784197001252... e-51')``[/color]
          >
          > Clearly, j is the correct answer. It's not all that hard to do, either.[/color]

          No way. Consider:
          [color=blue][color=green][color=darkred]
          >>> 1.1[/color][/color][/color]
          1.1000000000000 001[color=blue][color=green][color=darkred]
          >>> 1.1==1.10000000 00000001[/color][/color][/color]
          True

          So what should Decimal(1.10000 00000000001) evaluate to? It can't be
          Decimal('1.1'), as that contradicts your statement that j "clearly"
          applies. But it *also* can't be Decimal('1.1000 000000000001'), as then
          we have the *same number* converting to two *different* Decimal
          values.

          As I say, it's hard.

          I'd probably support Decimal(float) giving an exception, on the basis
          that if you're doing this, you probably don't know what you're getting
          into :-) Having a special method, say Decimal.round_f loat(f, digits),
          is probably OK, though...

          Paul.
          --
          This signature intentionally left blank

          Comment

          • John Roth

            #6
            Re: prePEP: Decimal data type


            "Alex Martelli" <aleaxit@yahoo. com> wrote in message
            news:KCQob.7827 5$e5.2907092@ne ws1.tin.it...[color=blue]
            > John Roth wrote:
            >[color=green]
            > > Lots of comments in line. See especially the comment
            > > about *NOT* wanting limited precision, as envisioned
            > > in the referenced decimal *floating point* standards.[/color]
            > ...[color=green]
            > > Since we've got infinite precision integer arithmetic, going to
            > > limited precision decimal arithmetic is, IMNSHO, a step backwards.[/color]
            >
            > There may be a niche for a Rational data type, but in MHO it cannot take[/color]
            the[color=blue]
            > place of a limited-precision-decimal (fixed or float). I suggest you[/color]
            think[color=blue]
            > of a separate PEP to propose Rational (check the existing and rejected[/color]
            ones[color=blue]
            > first, there may be some that are relevant) rather than attacking this[/color]
            one.

            Alex, where did I suggest that I wanted a rational data type? Please
            tell me one place in my response where I said that. Please?

            For the record. I'm not suggesting a rational data type. I'm quite
            well aware of the arguements pro and con, and Guido's position.
            Please read what I said without your preconceptions.

            The only place where you can get into trouble is with division
            and equivalent operations. That's the one place where you actually
            need to specify the result number of decimal places and the rounding
            policy. Every other operation has a well defined result that won't
            ever lead to repeating decimal representations , etc.

            My basic suggestion for that is to replace the division operators
            with a div() function that lets you specify the number of places
            and the rounding policy.

            John Roth

            [color=blue]
            >
            >
            > Alex
            >[/color]


            Comment

            • John Roth

              #7
              Re: prePEP: Decimal data type


              "Paul Moore" <pf_moore@yahoo .co.uk> wrote in message
              news:3cd884n4.f sf@yahoo.co.uk. ..[color=blue]
              > "John Roth" <newsgroups@jhr othjr.com> writes:
              >[color=green][color=darkred]
              > >> The idea is to have a Decimal data type, for every use where decimals[/color][/color][/color]
              are[color=blue][color=green][color=darkred]
              > >> 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.[/color]
              > >
              > > 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.[/color]
              >
              > To be honest, I have little if any practical experience with numeric
              > representation issues, but it seems sensible to me to implement a
              > pre-existing, and presumably well thought out, standard, rather than
              > inventing something ad-hoc.
              >
              > Of course, if the need is for something other than what ANSI 274
              > standardises, which seems to be what you are implying, then fair
              > enough. But what do you require? Infinite-precision decimal
              > arithmetic? If so, can you explain how you'd handle something like
              > 1/3?[/color]

              As I said in the response to Alex, division is the one place where
              fixed decimal gets into trouble. To repeat what I said to him,
              I'd eliminate the division operators completely, and replace them
              with a div(dividend, divisor, [resultplaces], [roundingpolicy])
              operator.

              The division operators make a hidden assumption that they
              know what you want. That's ok for floating point, and it's
              inherent for rationals, but it doesn't really work for integers
              or fixed decimal.

              In the spirit of explicit is better than implicit, I'd rather have
              the control inherent in a div() operator.


              [color=blue]
              >
              > (I'm not being deliberately awkward here - my impression is that
              > representation issues are *hard*, and there are a lot of traps you can
              > fall into by oversimplifying . That's why I prefer the idea of a
              > pre-existing standard: it implies that *someone* has thought about the
              > hard stuff).
              >[color=green]
              > > 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.[/color]
              >
              > Even infinite precision integers throw away information, in some
              > sense. Witness:
              >[color=green][color=darkred]
              > >>> 1L//3L[/color][/color]
              > 0L[/color]

              Same comment. Integer division, as it's currently implemented, is
              simply wrong. However, we had that discussion and decided to
              take one of the several different approaches, flying in the face
              of the evidence that any choice was not going to be useable in
              some context.

              When you try to simplify an inherently complex situation by
              putting a pretty face on it, all you do is confuse the issue more.
              [color=blue]
              >[color=green][color=darkred]
              > >> When passing floating point to the constructor, what should happen?
              > >>
              > >> j. ``Decimal(1.1) == Decimal('1.1')` `
              > >> k. ``Decimal(1.1) ==
              > >> Decimal('110000 000000000008881 784197001252... e-51')``[/color]
              > >
              > > Clearly, j is the correct answer. It's not all that hard to do, either.[/color]
              >
              > No way. Consider:
              >[color=green][color=darkred]
              > >>> 1.1[/color][/color]
              > 1.1000000000000 001[color=green][color=darkred]
              > >>> 1.1==1.10000000 00000001[/color][/color]
              > True
              >
              > So what should Decimal(1.10000 00000000001) evaluate to? It can't be
              > Decimal('1.1'), as that contradicts your statement that j "clearly"
              > applies. But it *also* can't be Decimal('1.1000 000000000001'), as then
              > we have the *same number* converting to two *different* Decimal
              > values.
              >
              > As I say, it's hard.[/color]

              Not that hard. It's not at all difficult to find where the actual number
              ends and where the fuzz begins. You can do it visually, and the
              algorithms to do it are quite well known. That's how printing libraries
              handle the issue, after all.

              You can also special case that with some lightweight compiler
              magic. All that really has to happen is that the lexer has to pass
              the 1.1 to the compiler without converting it to a float first,
              then the parser can apply a special rule when it sees that token
              in the context of decimal(1.1).

              [color=blue]
              > I'd probably support Decimal(float) giving an exception, on the basis
              > that if you're doing this, you probably don't know what you're getting
              > into :-) Having a special method, say Decimal.round_f loat(f, digits),
              > is probably OK, though...[/color]

              I think someone earlier suggested (in the context of the Money type)
              having the number of digits be an optional arguement to the constructor.
              That is: decimal(1.1, 1) showing one place after the decimal point.

              However, I prefer having the compiler take care of it.

              John Roth[color=blue]
              >
              > Paul.
              > --
              > This signature intentionally left blank[/color]


              Comment

              • Irmen de Jong

                #8
                Re: prePEP: Decimal data type

                John Roth wrote:
                [color=blue]
                > In the spirit of explicit is better than implicit, I'd rather have
                > the control inherent in a div() operator.[/color]

                +1 (without having read all of the thread, but John's
                statement sounds very reasonable to me)
                [color=blue]
                > I think someone earlier suggested (in the context of the Money type)
                > having the number of digits be an optional arguement to the constructor.
                > That is: decimal(1.1, 1) showing one place after the decimal point.
                >
                > However, I prefer having the compiler take care of it.[/color]

                I think I don't. Consider:

                d=decimal(1.1)

                versus:

                f = 1.1
                d = decimal(f)

                this would yield different results then. And I think that's confusing.

                Although decimal(1.1,1) -with the extra argument "1 decimal place"-
                isn't really pretty either, IMHO: you have to actually count the
                number of decimal digits yourself!

                --Irmen de Jong

                Comment

                • Alex Martelli

                  #9
                  Re: prePEP: Decimal data type

                  John Roth wrote:
                  ...[color=blue]
                  > Not that hard. It's not at all difficult to find where the actual number
                  > ends and where the fuzz begins. You can do it visually, and the
                  > algorithms to do it are quite well known. That's how printing libraries
                  > handle the issue, after all.[/color]

                  There are several heuristics, but "printing libraries" (???) have nothing
                  to do with the issue. I have adopted one such heuristic (Stern-Brocot)
                  in gmpy at the request of P. Peterson, and there are other popular ones
                  such as Farey Fractions. But none is at all perfect.
                  [color=blue]
                  > You can also special case that with some lightweight compiler
                  > magic. All that really has to happen is that the lexer has to pass
                  > the 1.1 to the compiler without converting it to a float first,
                  > then the parser can apply a special rule when it sees that token
                  > in the context of decimal(1.1).[/color]

                  So you are proposing that, in this *ONE PLACE* out of ALL the huge
                  variety in the Python language,

                  x = 1.1
                  ....
                  y = decimal(x)

                  give a DIFFERENT result than

                  y = decimal(1.1)

                  ??? This is just _not in the cards_. Python's regularity, uniformity,
                  and simplicity, are FAR more important than any one "special case" can
                  possibly be. Or, as the Zen of Python puts it, "special cases aren't
                  special enough to break the rules".

                  [color=blue]
                  > I think someone earlier suggested (in the context of the Money type)
                  > having the number of digits be an optional arguement to the constructor.
                  > That is: decimal(1.1, 1) showing one place after the decimal point.[/color]

                  Constructing with some specified precision (not "SHOWING" but actually
                  constructing) would be fine. "Places after the decimal point" may or
                  may not be the ideal way to specify precision, that's a different issue
                  (if there are any applicable standards, I'd go for those, rather than
                  make any arbitrary decision in the matter). But letting the precision
                  default if left unspecified -- and thus letting construction from floats
                  just happen -- is a far different decision. Naive users will always
                  _believe_ that they're getting "good" precision, if they think at all
                  about the matter (which unfortunately they may not), unless they _are_
                  forced to think about the subject by needing to specify precision very
                  explicitly. Thus, I think "constructi on from float with some default
                  precision" runs a substantial risk of tricking naive users.


                  Alex

                  Comment

                  • John Roth

                    #10
                    Re: prePEP: Decimal data type


                    "Alex Martelli" <aleax@aleax.it > wrote in message
                    news:a%Rob.3942 17$R32.13072021 @news2.tin.it.. .[color=blue]
                    > John Roth wrote:
                    > ...[/color]

                    [snip]
                    I decided to snip the prior piece rather than argue about your
                    misconception of what I intended. This would have been obvious
                    if you had left the context of my comment in, rather than starting
                    it out with my response to something invisible to the reader.
                    [color=blue][color=green]
                    > > I think someone earlier suggested (in the context of the Money type)
                    > > having the number of digits be an optional arguement to the constructor.
                    > > That is: decimal(1.1, 1) showing one place after the decimal point.[/color]
                    >
                    > Constructing with some specified precision (not "SHOWING" but actually
                    > constructing) would be fine. "Places after the decimal point" may or
                    > may not be the ideal way to specify precision, that's a different issue
                    > (if there are any applicable standards, I'd go for those, rather than
                    > make any arbitrary decision in the matter). But letting the precision
                    > default if left unspecified -- and thus letting construction from floats
                    > just happen -- is a far different decision. Naive users will always
                    > _believe_ that they're getting "good" precision, if they think at all
                    > about the matter (which unfortunately they may not), unless they _are_
                    > forced to think about the subject by needing to specify precision very
                    > explicitly. Thus, I think "constructi on from float with some default
                    > precision" runs a substantial risk of tricking naive users.[/color]

                    I agree with that. I'd just as soon require that the precision
                    be specified if the input is a float.

                    As far as using number of places after the decimal point, rather
                    than some other unit, I will admit that I can't think of another unit.

                    John Roth[color=blue]
                    >
                    >
                    > Alex
                    >[/color]


                    Comment

                    • John Roth

                      #11
                      Re: prePEP: Decimal data type


                      "Irmen de Jong" <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message
                      news:3fa3e7fb$0 $58697$e4fe514c @news.xs4all.nl ...[color=blue]
                      > John Roth wrote:
                      >[color=green]
                      > > In the spirit of explicit is better than implicit, I'd rather have
                      > > the control inherent in a div() operator.[/color]
                      >
                      > +1 (without having read all of the thread, but John's
                      > statement sounds very reasonable to me)
                      >[color=green]
                      > > I think someone earlier suggested (in the context of the Money type)
                      > > having the number of digits be an optional arguement to the constructor.
                      > > That is: decimal(1.1, 1) showing one place after the decimal point.
                      > >
                      > > However, I prefer having the compiler take care of it.[/color]
                      >
                      > I think I don't. Consider:
                      >
                      > d=decimal(1.1)
                      >
                      > versus:
                      >
                      > f = 1.1
                      > d = decimal(f)
                      >
                      > this would yield different results then. And I think that's confusing.
                      >
                      > Although decimal(1.1,1) -with the extra argument "1 decimal place"-
                      > isn't really pretty either, IMHO: you have to actually count the
                      > number of decimal digits yourself![/color]

                      See Alex's comment, and my response. I agree it isn't pretty,
                      but the alternatives seem to be worse.

                      John Roth[color=blue]
                      >
                      > --Irmen de Jong
                      >[/color]


                      Comment

                      • Alex Martelli

                        #12
                        Re: prePEP: Decimal data type

                        John Roth wrote:
                        ...[color=blue]
                        > Alex, where did I suggest that I wanted a rational data type? Please
                        > tell me one place in my response where I said that. Please?[/color]

                        You fought against limited precision, and said NOTHING against
                        the requirement that the new type support division (point 12 in
                        the specs). This implies the implementation must use rationals
                        (by any other name). Of course, if you now change your responses
                        (and in particular change the lack of objection to / into a
                        request that it be abrogated, as you do below) then (at least
                        some of) the objections to your proposals change (the one against
                        the crazy idea of having number+string implicitly convert the
                        string "just as if" it had been explicitly converted stands, of
                        course -- "if you want Perl, you know where to find it").

                        [color=blue]
                        > For the record. I'm not suggesting a rational data type. I'm quite
                        > well aware of the arguements pro and con, and Guido's position.
                        > Please read what I said without your preconceptions.[/color]

                        I have no preconceptions about what your opinions of various
                        number kinds may be: I simply read your post, and if in that
                        post you say *NOT A WORD* against division, how can you expect
                        any reader to divine that you want to abolish it?! Cheez --
                        what about learning to write, rather than chiding others for
                        not reading your mind but rather just reading what you write
                        and what you _don't_ write?!

                        [color=blue]
                        > The only place where you can get into trouble is with division
                        > and equivalent operations. That's the one place where you actually[/color]

                        If one accepts that an arbitrary float is somehow (perhaps a bit
                        arbitrarily) coerced into a decimal-fraction before operating
                        (e.g. by multiplication) -- or forbids such mixed-type operations,
                        against your expressed wishes -- yes.

                        The resulting decimal type, however, may not be highly usable
                        for some kinds of monetary computations. It's an unfortunate
                        but undisputable fact of life that laws and regulations exist
                        that specify some monetary computations in detailed ways that
                        differ from each other. E.g., in the EU all computations must
                        be carried out to the hundredth of an Euro, no less and *no
                        more*, with rounding as specified in the regulations (I quoted
                        them extensively in the preceding python-dev discussion which
                        you may find in the archives) -- the laws indicate that this
                        may give "off by one cent" results compared with exact arithmetic,
                        with examples, and mandate that this one-cent difference be
                        accepted as it derives from application of their exact rules
                        (they even specifically note that reconciling accounts will be
                        made too hard unless computer programs and similar equipment
                        all follow these exact rumes). Other jurisdictions have
                        different rules and regulations -- e.g., not sure if there still
                        are such markets, but once US financial markets mandated the
                        accounting to be in 1/16th of a dollar (which is _not_ the same
                        thing as arithmetic in hundredths of a cent -- most values you
                        might obtain with the latter are not valid in the former).

                        Say that a charge that is specified by law as 2.6473% is to be
                        computed on each unit of a stock currently worth 2.33 currency
                        units. The resulting "exact" amount of 0.06168209 must be
                        treated as "exactly" 6 Eurocents in the EU; this will cause an
                        off-by-one (and thus by a lot depending how many units of stock
                        you have), but if this is the computation the law specifies,
                        this is the one you have to perform. If laws and regulations
                        mandated accounting in 16th of a currency unit, you'd have to
                        consider that amount as 1/16th, i.e. 0.625 -- "erring" the other
                        way. In neither case would it be acceptable to carry around the
                        "exact" amount and then say, for example, to a customer who owns
                        1000 units of the stock, that he must pay a charge of 6.168209
                        dollars or euros (not even if you rounded it to 6.17 _at this
                        stage_) -- in one case you would overcharging by 16.8209 (or 17
                        cents), in the other, undercharging by 8 cents wrt the 6.25 the
                        tax authorities will later want.

                        I realize worrying about these 8 or 17 cents _seems_ silly, but,
                        it IS what accountants *DO* -- and if one writes accounting
                        software one should really play by their rules (or be Microsoft,
                        who feels free to have "rules" in VB and [different ones, I'm
                        told] Excel arithmetic which drive accountants batty:-).

                        Note that the operation that gives trouble here is not a
                        division -- it's a multiplication. The problem is with carrying
                        around "unbounded precision" _when laws and regulations
                        tell you otherwise_. Forcing the user to remember to round
                        again (by calling the appropriate rounding function) after every
                        multiplication is dangerous, because subtly wrong but plausible
                        results will come if the user forgets one of those calls. The
                        sensible approach would seem to be to imbue every Decimal instance
                        with the rounding rules that instance is supposed to follow (in
                        most programs the rules will be the same for every instance, but
                        _allowing_, albeit with some trouble if need be, particularly
                        complicated programs to carry on computations with several
                        different sets of rules, would be good -- as long as no accidental
                        and incorrect "mix" of them can happen by mistake).


                        There may be use cases where "unbounded precision" is the rule
                        that an application needs and yet ease of division is not needed.

                        I'm not sure there are any easy examples (e.g., in a purely
                        indicative "what if" scenario it might be cool to keep unbounded
                        precision if performance allowed -- although in that case I
                        suspect "error-bounds propagation" might be even more useful --
                        but for such [not-necessarily-quick-but]-dirty computations, the
                        inability to just divide with / would be a bit cumbersome) but
                        surely there may be some (it's up to advocates of your variant
                        of "unbounded precision" to come up with real use cases for them,
                        of course). But the bread-and-butter use cases for computations
                        with money don't require unbounded precision and in fact may be
                        worse off with it when it conflicts with laws and regulations --
                        specified precision rules per Decimal instance looks therefore like
                        a vastly preferable solution, and the special case of unbounded
                        precision may be handled either by allowing "unbounded precision"
                        as one of the special precision/rounding rules sets, or making a
                        specialcase 'unboundeddecim al' type, perhaps a subclass of the
                        ordinary bounded-precision decimal type, if implementation turns
                        out to be simpler that way.
                        [color=blue]
                        > need to specify the result number of decimal places and the rounding
                        > policy. Every other operation has a well defined result that won't
                        > ever lead to repeating decimal representations , etc.[/color]

                        No, but repeating decimals are not the only problem; and the rules
                        of unbounded precision are not the only ones in town, so the "well
                        defined result" they produce need not be the same as the "well
                        defined result" produced by other rules which laws or regulations
                        (more often than not based on specified finite precision) mandate.

                        [color=blue]
                        > My basic suggestion for that is to replace the division operators
                        > with a div() function that lets you specify the number of places
                        > and the rounding policy.[/color]

                        I have no issue with that, but I definitely think that, to actually
                        be USEFUL in practice, Decimal instances should be able to carry
                        around their own precision and rounding-rules. Then you can use
                        explicit div and mul (functions or methods) when you want to
                        explicitly specify something different -- probably add and sub too,
                        when you want to produce a Decimal that may have different rules
                        as a result, or explicitly "mix" (operate betweem) instances that
                        might have different and possibly conflicting rules. But you can
                        also use the ordinary operators in ordinary circumstances when you
                        are operating between instances that have the same rules. In
                        this case, I think that add(a,b) , mul(a,b) , etc, without specific
                        parameters for precision, rounding, nor other rules, might be
                        totally equivalent to a+b , a*b , etc. It costs nothing and it
                        might endear us a little bit to the "migrating from Cobol" crowd
                        (OK, not as much as "add a to b" would, but we can't have that:-).


                        Alex

                        Comment

                        • John Roth

                          #13
                          Re: prePEP: Decimal data type


                          "Alex Martelli" <aleax@aleax.it > wrote in message
                          news:MTSob.7897 5$e5.2933818@ne ws1.tin.it...

                          Alex, I think we've lost context, so I'm going to state,
                          up front, the context I see for the discussion. More
                          detail is at the back of this post.

                          I'm quite happy with the notion of all the messy accounting
                          and regulatory details being handled by a money type that
                          is designed to keep the accountants and regulators happy,
                          at the expense of programming simplicity. I spent quite a
                          few years doing that type of programming; I think I know
                          a bit about it.

                          Given that, I don't see any real advantage in having a separate
                          decimal type that duplicates the functionality needed for
                          money. The decimal type should be directed more toward the
                          intuitive, ease of use angle that Python is famous for.

                          I also don't see a case for a floating decimal type. If you
                          have the money type, then there isn't a whole lot that
                          you can do with floating decimal that you can't do with
                          regualar binary floats.

                          I can see some justification for a simple, straightforward ,
                          fixed decimal type that makes reasonable assumptions in
                          corner cases, while still allowing the programmer a good
                          deal of control if she wants to exercise it.

                          That's the context of my remarks.

                          [color=blue]
                          > John Roth wrote:[/color]


                          [color=blue]
                          > ...[color=green]
                          > > Alex, where did I suggest that I wanted a rational data type? Please
                          > > tell me one place in my response where I said that. Please?[/color]
                          >
                          > You fought against limited precision, and said NOTHING against
                          > the requirement that the new type support division (point 12 in
                          > the specs). This implies the implementation must use rationals
                          > (by any other name).[/color]

                          The alternative explanation is that I simply hadn't thought that
                          part of the issue through when I made the response. It's a
                          much simpler explanation, isn't it?
                          [color=blue]
                          > Of course, if you now change your responses
                          > (and in particular change the lack of objection to / into a
                          > request that it be abrogated, as you do below) then (at least
                          > some of) the objections to your proposals change (the one against
                          > the crazy idea of having number+string implicitly convert the
                          > string "just as if" it had been explicitly converted stands, of
                          > course -- "if you want Perl, you know where to find it").[/color]

                          That's discussable, of course.
                          [color=blue]
                          >[color=green]
                          > > The only place where you can get into trouble is with division
                          > > and equivalent operations. That's the one place where you actually[/color]
                          >
                          > If one accepts that an arbitrary float is somehow (perhaps a bit
                          > arbitrarily) coerced into a decimal-fraction before operating
                          > (e.g. by multiplication) -- or forbids such mixed-type operations,
                          > against your expressed wishes -- yes.[/color]

                          If we're going to have to specify additional information
                          when we explicitly construct a decimal from a float, as
                          one variety of proposal suggests, then I see no difficulty
                          with prohibiting implicit conversions. In fact, I seem to
                          remember a note that implicit type coercion may vanish
                          sometime in the misty future (3.0 time frame.)
                          [color=blue]
                          > The resulting decimal type, however, may not be highly usable
                          > for some kinds of monetary computations.[/color]

                          I think that was the justification for a separate money
                          data type.
                          [color=blue]
                          > It's an unfortunate
                          > but undisputable fact of life that laws and regulations exist
                          > that specify some monetary computations in detailed ways that
                          > differ from each other.[/color]

                          Understood, in detail.

                          [...]
                          [color=blue]
                          > Note that the operation that gives trouble here is not a
                          > division -- it's a multiplication. The problem is with carrying
                          > around "unbounded precision" _when laws and regulations
                          > tell you otherwise_. Forcing the user to remember to round
                          > again (by calling the appropriate rounding function) after every
                          > multiplication is dangerous, because subtly wrong but plausible
                          > results will come if the user forgets one of those calls. The
                          > sensible approach would seem to be to imbue every Decimal instance
                          > with the rounding rules that instance is supposed to follow (in
                          > most programs the rules will be the same for every instance, but
                          > _allowing_, albeit with some trouble if need be, particularly
                          > complicated programs to carry on computations with several
                          > different sets of rules, would be good -- as long as no accidental
                          > and incorrect "mix" of them can happen by mistake).[/color]

                          That is, in fact, the way money needs to be handled. However,
                          I was under the impression that the separate money type was
                          still in play, for the reasons stated in the pre-pep.

                          [...]
                          [color=blue]
                          > I have no issue with that, but I definitely think that, to actually
                          > be USEFUL in practice, Decimal instances should be able to carry
                          > around their own precision and rounding-rules. Then you can use
                          > explicit div and mul (functions or methods) when you want to
                          > explicitly specify something different -- probably add and sub too,
                          > when you want to produce a Decimal that may have different rules
                          > as a result, or explicitly "mix" (operate betweem) instances that
                          > might have different and possibly conflicting rules. But you can
                          > also use the ordinary operators in ordinary circumstances when you
                          > are operating between instances that have the same rules. In
                          > this case, I think that add(a,b) , mul(a,b) , etc, without specific
                          > parameters for precision, rounding, nor other rules, might be
                          > totally equivalent to a+b , a*b , etc. It costs nothing and it
                          > might endear us a little bit to the "migrating from Cobol" crowd
                          > (OK, not as much as "add a to b" would, but we can't have that:-).[/color]

                          The base problem with this is that COBOL doesn't do it that
                          way, and COBOL was deliberately designed to do things the
                          way the accounting profession wanted, or at least make it
                          possible to do them without the language getting in your way.

                          Part of the reason why COBOL has the separate operators
                          is that the *destination* of the operation specifies how the
                          result is computed. You can't do that with intermediate
                          results if you use expression notation.

                          The only way you can do anything similar in a language like
                          Python is to avoid the operators and use functions or methods
                          that allow you to explicitly specify the exact form of the result,
                          together with the rounding rules, if any, used to get there.

                          Another thing that hasn't been brought up, though: COBOL
                          also allows you to specify a maximum for a value: you can't
                          exceed it without causing an overflow exception (which can
                          be caught with an ON OVERFLOW clause, of course.)

                          John Roth

                          [color=blue]
                          >
                          >
                          > Alex
                          >[/color]


                          Comment

                          • Alex Martelli

                            #14
                            Re: prePEP: Decimal data type

                            John Roth wrote:
                            ...[color=blue]
                            > I decided to snip the prior piece rather than argue about your
                            > misconception of what I intended. This would have been obvious
                            > if you had left the context of my comment in, rather than starting
                            > it out with my response to something invisible to the reader.[/color]

                            I prefer to trim posts from such generally irrelevant history,
                            but if you think "This would have been obvious" here is ALL you
                            had to say in your first post in response to the point, which
                            you quoted in full, about what operators should apply to decimals:

                            """[color=blue]
                            > 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.[/color]


                            [color=blue]
                            > 13. To support unary operators (``-, +, abs``).[/color]

                            OK.
                            """

                            Now try to argue _with a straight face_ that, quoting this part entirely, it
                            "would have been obvious" that you wanted to abrogate the applicability of
                            normal division operators to decimals, and therefore did not need as your
                            cherished "unbounded precision decimal" a full rational number in some
                            form. Pah.

                            Assuming that's what you intended in that post, I think you made a huge
                            mistake in NOT saying so, rather just placing a meek "OK" there, and are
                            now trying to imply that instead of your huge mistake there were some
                            "misconcept ion" (or as you said earlier, even LESS defensibly!,
                            "preconceptions " [!!!]) on MY part. In my view of the world, it's all
                            right to make a mistake (we're humans), but it's NOT ok to try to attack
                            others rather than admitting and apologizing for one's mistake.


                            Alex

                            Comment

                            • Ron Adam

                              #15
                              Re: prePEP: Decimal data type

                              On Fri, 31 Oct 2003 15:36:38 -0300, "Batista, Facundo"
                              <FBatista@uniFO N.com.ar> wrote:

                              [clip]
                              [color=blue]
                              >
                              >The Decimal data type should support the Python standard functions and
                              >operations and must comply the decimal arithmetic ANSI standard X3.274-1996.[/color]

                              Is this the correct ANSI number? I ended up at the following
                              websight.




                              _Ronald R. Adam


                              Comment

                              Working...