# A Revised Rational Proposal

Nick Coghlan ncoghlan at iinet.net.au
Mon Dec 27 03:52:26 CET 2004

```Dan Bishop wrote:
> Mike Meyer wrote:
>
>>This version includes the input from various and sundry people.
>
> Thanks
>
>>to everyone who contributed.
>>
>>   <mike
>>
>>PEP: XXX
>>Title: A rational number module for Python
>
> ...
>
>>Implicit Construction
>>---------------------
>>
>>When combined with a floating type - either complex or float - or a
>>decimal type, the result will be a TypeError.  The reason for this is
>>that floating point numbers - including complex - and decimals are
>>already imprecise.  To convert them to rational would give an
>>incorrect impression that the results of the operation are
>>precise. The proper way to add a rational to one of these types is to
>>convert the rational to that type explicitly before doing the
>>operation.
>
>
> I disagree with raising a TypeError here.  If, in mixed-type
> expressions, we treat ints as a special case of rationals, it's
> inconsistent for rationals to raise TypeErrors in situations where int
> doesn't.
>
>
>>>>2 + 0.5
>
> 2.5
>
>>>>Rational(2) + 0.5
>
> TypeError: unsupported operand types for +: 'Rational' and 'float'
>

Mike's use of this approach was based on the discussion around PEP 327 (Decimal).

The thing with Decimal and Rational is that they're both about known precision.
For Decimal, the decision was made that any operation that might lose that
precision should never be implicit.

Getting a type error gives the programmer a choice:
1. Take the precision loss in the result, by explicitly converting the Rational
to the imprecise type
2. Explicitly convert the non-Rational input to a Rational before the operation.

Permitting implicit conversion in either direction opens the door to precision
bugs - silent errors that even rigorous unit testing may not detect.

The seemingly benign ability to convert longs to floats implicitly is already a
potential source of precision bugs:

Py> bignum = 2 ** 62
Py> bignum
4611686018427387904L
Py> bignum + 1.0
4.6116860184273879e+018
Py> float(bignum) != bignum + 1.0
False

Cheers,
Nick.

--
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net

```