[Python-ideas] isinstance(Decimal(), Real) -> False?
Oscar Benjamin
oscar.j.benjamin at gmail.com
Wed Aug 28 15:13:10 CEST 2013
On 28 August 2013 13:32, Draic Kin <drekin at gmail.com> wrote:
> On Wed, Aug 28, 2013 at 1:35 PM, Oscar Benjamin <oscar.j.benjamin at gmail.com>
> wrote:
>>
>> The same is true of float but float(Fraction) happily works and so
>> does float(int), complex(int), float(Decimal) and Decimal(float)
>> (depending on the context Decimal can be either a subset or a superset
>> of float). A recent example where I wanted to do this was:
>>
>> def sum_exact(nums):
>> T = type(nums[0])
>> return T(sum(map(Fraction, nums)))
>>
>> The above sum function can happily sum anything that is convertible to
>> Fraction (which includes Decimals in Python 3.3). However
>> Decimal(Fraction) fails so you need something like:
>>
>> def sum_exact(nums):
>> T = type(nums[0])
>> if issubclass(T, Decimal):
>> return T.from_decimal(...)
>> else:
>> ...
>>
>> This just seems unnecessary to me.
>>
> Maybe it's because float and complex don't care for exactness. On the other
> hand Decimal always represent exactly the value of int and float but it
> cannot represent exactly the value of Fraction(1, 3). But if would be nice
> if one could make a decimal of given precision from fraction or make exact
> decimal representaion of a fraction if it is possible and raise exception
> otherwise.
But that's why the decimal module has the Inexact etc. traps.
Here's a table of coercions that are possible in 3.3. Key (i:int,
F:Fraction, D:Decimal, f:float, c:complex). If Tr is the type of the
row and Tc is the type of the column then X indicates that Tr(Tc) is
always possible and exact and R indicates that rounding may occur:
i F D f c
--+---------------
i | X R R R
F | X X X X
D | X X X
f | R R R X
c | R R R X X
There's a little hole in the middle there that makes the real types
not quite inter-operable. It's easy to implement the appropriate
conversion:
def decimal_from_rational(r):
# Result will be correctly rounded according to the current context.
# Raises any of the signals Clamped, InvalidOperation, DivisionByZero,
# Inexact, Rounded, Subnormal, Overflow, or Underflow as appropriate.
return Decimal(r.numerator) / Decimal(r.denominator)
But it's much more useful if that conversion takes place in Decimal.__new__.
Oscar
More information about the Python-ideas
mailing list