PEP: 239 Title: Adding a Rational Type to Python Author: Christopher A.
Craig <python-pep@ccraig.org>, Moshe Zadka <moshez@zadka.site.co.il>
Status: Rejected Type: Standards Track Created: 11-Mar-2001
Python-Version: 2.2 Post-History: 16-Mar-2001

The needs outlined in the rationale section have been addressed to some
extent by the acceptance of PEP 327 for decimal arithmetic. Guido also
noted, "Rational arithmetic was the default 'exact' arithmetic in ABC
and it did not work out as expected". See the python-dev discussion on
17 June 2005[1].

Postscript: With the acceptance of PEP 3141, "A Type Hierarchy for
Numbers", a 'Rational' numeric abstract base class was added with a
concrete implementation in the 'fractions' module.

Abstract

Python has no numeric type with the semantics of an unboundedly precise
rational number. This proposal explains the semantics of such a type,
and suggests builtin functions and literals to support such a type. This
PEP suggests no literals for rational numbers; that is left for
another PEP <240>.

Rationale

While sometimes slower and more memory intensive (in general,
unboundedly so) rational arithmetic captures more closely the
mathematical ideal of numbers, and tends to have behavior which is less
surprising to newbies. Though many Python implementations of rational
numbers have been written, none of these exist in the core, or are
documented in any way. This has made them much less accessible to people
who are less Python-savvy.

RationalType

There will be a new numeric type added called RationalType. Its unary
operators will do the obvious thing. Binary operators will coerce
integers and long integers to rationals, and rationals to floats and
complexes.

The following attributes will be supported: .numerator and .denominator.
The language definition will promise that:

    r.denominator * r == r.numerator

that the GCD of the numerator and the denominator is 1 and that the
denominator is positive.

The method r.trim(max_denominator) will return the closest rational s to
r such that abs(s.denominator) <= max_denominator.

The rational() Builtin

This function will have the signature rational(n, d=1). n and d must
both be integers, long integers or rationals. A guarantee is made that:

    rational(n, d) * d == n

Open Issues

-   Maybe the type should be called rat instead of rational. Somebody
    proposed that we have "abstract" pure mathematical types named
    complex, real, rational, integer, and "concrete" representation
    types with names like float, rat, long, int.

-   Should a rational number with an integer value be allowed as a
    sequence index? For example, should s[5/3 - 2/3] be equivalent to
    s[1]?

-   Should shift and mask operators be allowed for rational numbers? For
    rational numbers with integer values?

-   Marcin 'Qrczak' Kowalczyk summarized the arguments for and against
    unifying ints with rationals nicely on c.l.py

    Arguments for unifying ints with rationals:

    -   Since 2 == 2/1 and maybe str(2/1) == '2', it reduces surprises
        where objects seem equal but behave differently.
    -   / can be freely used for integer division when I know that there
        is no remainder (if I am wrong and there is a remainder, there
        will probably be some exception later).

    Arguments against:

    -   When I use the result of / as a sequence index, it's usually an
        error which should not be hidden by making the program working
        for some data, since it will break for other data.
    -   (this assumes that after unification int and rational would be
        different types:) Types should rarely depend on values. It's
        easier to reason when the type of a variable is known: I know
        how I can use it. I can determine that something is an int and
        expect that other objects used in this place will be ints too.
    -   (this assumes the same type for them:) Int is a good type in
        itself, not to be mixed with rationals. The fact that something
        is an integer should be expressible as a statement about its
        type. Many operations require ints and don't accept rationals.
        It's natural to think about them as about different types.

References

Copyright

This document has been placed in the public domain.

[1] Raymond Hettinger, Propose rejection of PEPs 239 and 240 -- a
builtin rational type and rational literals
https://mail.python.org/pipermail/python-dev/2005-June/054281.html