[Python-ideas] isinstance(Decimal(), Real) -> False?

Draic Kin drekin at gmail.com
Thu Aug 29 16:06:34 CEST 2013


On Thu, Aug 29, 2013 at 3:19 PM, Oscar Benjamin
<oscar.j.benjamin at gmail.com>wrote:

> On 29 August 2013 09:13, Draic Kin <drekin at gmail.com> wrote:
> > On Thu, Aug 29, 2013 at 4:02 AM, Steven D'Aprano <steve at pearwood.info>
> wrote:
> >> On 28/08/13 20:48, Draic Kin wrote:
> >>
> >>> and issubclass(Rational, Real) -> False. It's more about exact vs.
> >>> non-exact computations which is orthogonal to number hierarchy.
> >>
> >>
> >> The numeric tower is precisely about the numeric hierarchy of Number >
> >> Complex > Real > Rational > Integral, and since they are all *abstract*
> base
> >> classes, exact and inexact doesn't come into it. Concrete classes can be
> >> inexact or exact, or one could implement separate Exact and Inexact
> towers.
> >>
> >> In practice, it's hard to think of a concrete way to implement exact
> real
> >> numbers. Maybe a symbolic maths application like Mathematica comes
> close?
>
> Yes, Mathematica and more pertinently sympy implement exact real
> numbers. All fixed- or floating-point number formats are restricted to
> representing rational numbers. The obvious examples of exact
> irrational numbers are things like pi, e, sqrt(2) etc. Sympy can
> represent these exactly and guarantee that sqrt(n)**2 is exactly n for
> any integer n.
>
> >>> Maybe there
> >>> should be some ExactNumber abstract base class and some convention that
> >>> exact shouldn't coerce with non-exact. So Decimal + float should raise
> an
> >>> exception even if both would be subclasses of Real (and Decimal even of
> >>> Rational). Or maybe it would be enough if there were just non-exact
> >>> variants of Real and Complex since non-exactness if just issue of them.
> >>
> >> Personally, I would implement inexact/exact as an attribute on the type:
> >>
> >> if type(x).exact: ...
> >>
> >> sort of thing.
>
> Exactness is more complicated than that. Whether or not operation(a,
> b) is exact depends on:
> 1) the operation
> 2) the types of a AND b
> 3) the values of a and b
>
> For example if both operands are ints then results are exact for
> addition, subtraction, multiplication, and sometimes for division.
> Exponentiation is exact where the exponent is a non-negative integer
> but not if the exponent is negative. Fractions are exact for division
> also (except by 0) and for exponentiation where the exponent is any
> integer but not if the exponent is a non-integer valued Fraction (even
> if exact results are possible). int(num) is not exact unless num is an
> integer. Fraction(num) is always exact (or an error). The only senses
> in which Decimals are exact are that Decimal(str, Decimal(int) and
> Decimal(float) are exact and - if you set the Inexact trap - you can
> get an error any time something inexact would have otherwise occurred.
> (Well you could say that decimals are "exactly rounded" but that's not
> what we mean by exact here).
>
> > There were some points (possible against the idea of issubclass(Decimal,
> > Real) -> True) like Decimal doesn't coerce to float,
>
> Thinking about it now I would rather that float/Decimal operations
> coerce to Decimal and a FloatOperation error to be raised if set (by
> someone who doesn't want to mix Decimals and floats).
>
> > you cannot convert
> > Fraction to Decimal easily, you cannot sum Fraction + Decimal.
>
> These are just missing features IMO. Presumably if Decimal had been
> integrated into the numbers hierarchy these would have been added.
>
> To answer your original question, according to comments in sources of
decimal.py and numbers.py, Decimal shouldn't be subclass of Real since it
doesn't interoperate with floats and different subclasses of Real should
interoperate. From my point of view, if floats weren't more common that
decimals, one could turn the same argument around: Decimal subclasses Real
but float doesn't since it doesn't interoperate with Decimal. Maybe they
should interoperate and as you pointed out, Decimal is more robust in
handling errors so maybe float + Decimal should yield Decimal. Then Decimal
could be integrated to the number hierarchy.

Maybe there is still this problem: what would Decimal + complex return?

> Maybe some of
> > the rationale for the behavior is the matter of exact vs. non-exact.
>
> Decimals are not exact!
>

Got it now :-). I was thinking of Decimals as if they had always MAX_PREC
set.


>
> > So for
> > that reason the exactness rationale could be made explicit by adding some
> > indicator of exacness and base some coercion cases on this indicator.
>
> The coercion may be exact but the subsequent arithmetic operations are
> not. Preventing mixed Fraction/Decimal arithmetic does not save you
> rounding error:
>
> >>> d = decimal.Decimal('.1234')
> >>> f = fractions.Fraction('1/3')
> >>> d
> Decimal('0.1234')
> >>> f
> Fraction(1, 3)
> >>> d * f
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and
> 'Fraction'
>
> Well it's a good thing that type coercion saved us from being able to
> get rounding errors. Hang on...
>
> >>> d / 3
> Decimal('0.04113333333333333333333333333')
>
> That's the exact same rounding error we would have got with the Fraction!
>
> Any Decimal whose precision exceeds the current context precision will
> not have exact arithmetic operations (for any operation):
>
> >>> d = decimal.Decimal(11**30)
> >>> (d/3)*3 == d
> False
>
>
> Oscar
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130829/a90e39d0/attachment-0001.html>


More information about the Python-ideas mailing list