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

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[1].

BDFL Pronouncement

    This PEP is rejected.  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.

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

    [1] PEP 240, Adding a Rational Literal to Python, Zadka,
        http://www.python.org/peps/pep-0240.html


Copyright

    This document has been placed in the public domain.