Rename rational.Rational to fractions.Fraction, to avoid name clash

with numbers.Rational.  See issue #1682 for related discussion.
This commit is contained in:
Mark Dickinson 2008-02-10 21:29:51 +00:00
parent da614dcc4f
commit d058cd2cc8
7 changed files with 137 additions and 133 deletions

View File

@ -1,29 +1,29 @@
:mod:`rational` --- Rational numbers
:mod:`fractions` --- Rational numbers
====================================
.. module:: rational
.. module:: fractions
:synopsis: Rational numbers.
.. moduleauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. sectionauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. versionadded:: 2.6
The :mod:`rational` module defines an immutable, infinite-precision
Rational number class.
The :mod:`fractions` module defines an immutable, infinite-precision
Fraction number class.
.. class:: Rational(numerator=0, denominator=1)
Rational(other_rational)
Rational(string)
.. class:: Fraction(numerator=0, denominator=1)
Fraction(other_fraction)
Fraction(string)
The first version requires that *numerator* and *denominator* are
instances of :class:`numbers.Integral` and returns a new
``Rational`` representing ``numerator/denominator``. If
``Fraction`` representing ``numerator/denominator``. If
*denominator* is :const:`0`, raises a :exc:`ZeroDivisionError`. The
second version requires that *other_rational* is an instance of
second version requires that *other_fraction* is an instance of
:class:`numbers.Rational` and returns an instance of
:class:`Rational` with the same value. The third version expects a
:class:`Fraction` with the same value. The third version expects a
string of the form ``[-+]?[0-9]+(/[0-9]+)?``, optionally surrounded
by spaces.
@ -31,39 +31,39 @@ Rational number class.
:class:`numbers.Rational` and is immutable and hashable.
.. method:: Rational.from_float(flt)
.. method:: Fraction.from_float(flt)
This classmethod constructs a :class:`Rational` representing the
This classmethod constructs a :class:`Fraction` representing the
exact value of *flt*, which must be a :class:`float`. Beware that
``Rational.from_float(0.3)`` is not the same value as ``Rational(3,
``Fraction.from_float(0.3)`` is not the same value as ``Fraction(3,
10)``
.. method:: Rational.from_decimal(dec)
.. method:: Fraction.from_decimal(dec)
This classmethod constructs a :class:`Rational` representing the
This classmethod constructs a :class:`Fraction` representing the
exact value of *dec*, which must be a
:class:`decimal.Decimal`.
.. method:: Rational.__floor__()
.. method:: Fraction.__floor__()
Returns the greatest :class:`int` ``<= self``. Will be accessible
through :func:`math.floor` in Py3k.
.. method:: Rational.__ceil__()
.. method:: Fraction.__ceil__()
Returns the least :class:`int` ``>= self``. Will be accessible
through :func:`math.ceil` in Py3k.
.. method:: Rational.__round__()
Rational.__round__(ndigits)
.. method:: Fraction.__round__()
Fraction.__round__(ndigits)
The first version returns the nearest :class:`int` to ``self``,
rounding half to even. The second version rounds ``self`` to the
nearest multiple of ``Rational(1, 10**ndigits)`` (logically, if
nearest multiple of ``Fraction(1, 10**ndigits)`` (logically, if
``ndigits`` is negative), again rounding half toward even. Will be
accessible through :func:`round` in Py3k.

View File

@ -106,7 +106,7 @@ Notes for type implementors
Implementors should be careful to make equal numbers equal and hash
them to the same values. This may be subtle if there are two different
extensions of the real numbers. For example, :class:`rational.Rational`
extensions of the real numbers. For example, :class:`fractions.Fraction`
implements :func:`hash` as follows::
def __hash__(self):
@ -201,11 +201,11 @@ in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
Because most of the operations on any given type will be very similar,
it can be useful to define a helper function which generates the
forward and reverse instances of any given operator. For example,
:class:`rational.Rational` uses::
:class:`fractions.Fraction` uses::
def _operator_fallbacks(monomorphic_operator, fallback_operator):
def forward(a, b):
if isinstance(b, (int, long, Rational)):
if isinstance(b, (int, long, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@ -217,7 +217,7 @@ forward and reverse instances of any given operator. For example,
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
if isinstance(a, RationalAbc):
if isinstance(a, Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@ -233,7 +233,7 @@ forward and reverse instances of any given operator. For example,
def _add(a, b):
"""a + b"""
return Rational(a.numerator * b.denominator +
return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)

View File

@ -578,8 +578,8 @@ and comparisons.
:class:`Rational` numbers derive from :class:`Real`, have
:attr:`numerator` and :attr:`denominator` properties, and can be
converted to floats. Python 2.6 adds a simple rational-number class
in the :mod:`rational` module.
converted to floats. Python 2.6 adds a simple rational-number class,
:class:`Fraction`, in the :mod:`fractions` module.
:class:`Integral` numbers derive from :class:`Rational`, and
can be shifted left and right with ``<<`` and ``>>``,
@ -598,29 +598,29 @@ one, :func:`trunc`, that's been backported to Python 2.6.
The Rational Module
The Fraction Module
--------------------------------------------------
To fill out the hierarchy of numeric types, a rational-number class
has been added as the :mod:`rational` module. Rational numbers are
has been added as the :mod:`fractions` module. Rational numbers are
represented as a fraction; rational numbers can exactly represent
numbers such as two-thirds that floating-point numbers can only
approximate.
The :class:`Rational` constructor takes two :class:`Integral` values
The :class:`Fraction` constructor takes two :class:`Integral` values
that will be the numerator and denominator of the resulting fraction. ::
>>> from rational import Rational
>>> a = Rational(2, 3)
>>> b = Rational(2, 5)
>>> from fractions import Fraction
>>> a = Fraction(2, 3)
>>> b = Fraction(2, 5)
>>> float(a), float(b)
(0.66666666666666663, 0.40000000000000002)
>>> a+b
rational.Rational(16,15)
Fraction(16,15)
>>> a/b
rational.Rational(5,3)
Fraction(5,3)
The :mod:`rational` module is based upon an implementation by Sjoerd
The :mod:`fractions` module is based upon an implementation by Sjoerd
Mullender that was in Python's :file:`Demo/classes/` directory for a
long time. This implementation was significantly updated by Jeffrey
Yaskin.

View File

@ -9,9 +9,9 @@ import numbers
import operator
import re
__all__ = ["Rational"]
__all__ = ["Fraction"]
RationalAbc = numbers.Rational
Rational = numbers.Rational
def gcd(a, b):
@ -39,15 +39,15 @@ _RATIONAL_FORMAT = re.compile(r"""
""", re.VERBOSE)
class Rational(RationalAbc):
class Fraction(Rational):
"""This class implements rational numbers.
Rational(8, 6) will produce a rational number equivalent to
Fraction(8, 6) will produce a rational number equivalent to
4/3. Both arguments must be Integral. The numerator defaults to 0
and the denominator defaults to 1 so that Rational(3) == 3 and
Rational() == 0.
and the denominator defaults to 1 so that Fraction(3) == 3 and
Fraction() == 0.
Rationals can also be constructed from strings of the form
Fractions can also be constructed from strings of the form
'[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
"""
@ -56,13 +56,13 @@ class Rational(RationalAbc):
# We're immutable, so use __new__ not __init__
def __new__(cls, numerator=0, denominator=1):
"""Constructs a Rational.
"""Constructs a Fraction.
Takes a string like '3/2' or '1.5', another Rational, or a
Takes a string like '3/2' or '1.5', another Fraction, or a
numerator/denominator pair.
"""
self = super(Rational, cls).__new__(cls)
self = super(Fraction, cls).__new__(cls)
if denominator == 1:
if isinstance(numerator, basestring):
@ -70,7 +70,7 @@ class Rational(RationalAbc):
input = numerator
m = _RATIONAL_FORMAT.match(input)
if m is None:
raise ValueError('Invalid literal for Rational: ' + input)
raise ValueError('Invalid literal for Fraction: ' + input)
numerator = m.group('num')
decimal = m.group('decimal')
if decimal:
@ -87,7 +87,7 @@ class Rational(RationalAbc):
numerator = -numerator
elif (not isinstance(numerator, numbers.Integral) and
isinstance(numerator, RationalAbc)):
isinstance(numerator, Rational)):
# Handle copies from other rationals.
other_rational = numerator
numerator = other_rational.numerator
@ -95,11 +95,11 @@ class Rational(RationalAbc):
if (not isinstance(numerator, numbers.Integral) or
not isinstance(denominator, numbers.Integral)):
raise TypeError("Rational(%(numerator)s, %(denominator)s):"
raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
" Both arguments must be integral." % locals())
if denominator == 0:
raise ZeroDivisionError('Rational(%s, 0)' % numerator)
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
g = gcd(numerator, denominator)
self._numerator = int(numerator // g)
@ -110,15 +110,15 @@ class Rational(RationalAbc):
def from_float(f):
"""Converts a finite float to a rational number, exactly.
Beware that Rational.from_float(0.3) != Rational(3, 10).
Beware that Fraction.from_float(0.3) != Fraction(3, 10).
"""
if not isinstance(f, float):
raise TypeError("Rational.from_float() only takes floats, "
raise TypeError("Fraction.from_float() only takes floats, "
"not %r (%s)" % (f, type(f).__name__))
if math.isnan(f) or math.isinf(f):
raise TypeError("Cannot convert %r to Rational." % f)
return Rational(*f.as_integer_ratio())
raise TypeError("Cannot convert %r to Fraction." % f)
return Fraction(*f.as_integer_ratio())
@staticmethod
def from_decimal(dec):
@ -126,28 +126,28 @@ class Rational(RationalAbc):
from decimal import Decimal
if not isinstance(dec, Decimal):
raise TypeError(
"Rational.from_decimal() only takes Decimals, not %r (%s)" %
"Fraction.from_decimal() only takes Decimals, not %r (%s)" %
(dec, type(dec).__name__))
if not dec.is_finite():
# Catches infinities and nans.
raise TypeError("Cannot convert %s to Rational." % dec)
raise TypeError("Cannot convert %s to Fraction." % dec)
sign, digits, exp = dec.as_tuple()
digits = int(''.join(map(str, digits)))
if sign:
digits = -digits
if exp >= 0:
return Rational(digits * 10 ** exp)
return Fraction(digits * 10 ** exp)
else:
return Rational(digits, 10 ** -exp)
return Fraction(digits, 10 ** -exp)
@staticmethod
def from_continued_fraction(seq):
'Build a Rational from a continued fraction expessed as a sequence'
'Build a Fraction from a continued fraction expessed as a sequence'
n, d = 1, 0
for e in reversed(seq):
n, d = d, n
n += e * d
return Rational(n, d) if seq else Rational(0)
return Fraction(n, d) if seq else Fraction(0)
def as_continued_fraction(self):
'Return continued fraction expressed as a list'
@ -169,7 +169,7 @@ class Rational(RationalAbc):
if self.denominator <= max_denominator:
return self
cf = self.as_continued_fraction()
result = Rational(0)
result = Fraction(0)
for i in range(1, len(cf)):
new = self.from_continued_fraction(cf[:i])
if new.denominator > max_denominator:
@ -187,7 +187,7 @@ class Rational(RationalAbc):
def __repr__(self):
"""repr(self)"""
return ('Rational(%r,%r)' % (self.numerator, self.denominator))
return ('Fraction(%r,%r)' % (self.numerator, self.denominator))
def __str__(self):
"""str(self)"""
@ -207,13 +207,13 @@ class Rational(RationalAbc):
that mixed-mode operations either call an implementation whose
author knew about the types of both arguments, or convert both
to the nearest built in type and do the operation there. In
Rational, that means that we define __add__ and __radd__ as:
Fraction, that means that we define __add__ and __radd__ as:
def __add__(self, other):
# Both types have numerators/denominator attributes,
# so do the operation directly
if isinstance(other, (int, long, Rational)):
return Rational(self.numerator * other.denominator +
if isinstance(other, (int, long, Fraction)):
return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
# float and complex don't have those operations, but we
@ -228,8 +228,8 @@ class Rational(RationalAbc):
def __radd__(self, other):
# radd handles more types than add because there's
# nothing left to fall back to.
if isinstance(other, RationalAbc):
return Rational(self.numerator * other.denominator +
if isinstance(other, Rational):
return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
elif isinstance(other, Real):
@ -240,32 +240,32 @@ class Rational(RationalAbc):
There are 5 different cases for a mixed-type addition on
Rational. I'll refer to all of the above code that doesn't
refer to Rational, float, or complex as "boilerplate". 'r'
will be an instance of Rational, which is a subtype of
RationalAbc (r : Rational <: RationalAbc), and b : B <:
Fraction. I'll refer to all of the above code that doesn't
refer to Fraction, float, or complex as "boilerplate". 'r'
will be an instance of Fraction, which is a subtype of
Rational (r : Fraction <: Rational), and b : B <:
Complex. The first three involve 'r + b':
1. If B <: Rational, int, float, or complex, we handle
1. If B <: Fraction, int, float, or complex, we handle
that specially, and all is well.
2. If Rational falls back to the boilerplate code, and it
2. If Fraction falls back to the boilerplate code, and it
were to return a value from __add__, we'd miss the
possibility that B defines a more intelligent __radd__,
so the boilerplate should return NotImplemented from
__add__. In particular, we don't handle RationalAbc
__add__. In particular, we don't handle Rational
here, even though we could get an exact answer, in case
the other type wants to do something special.
3. If B <: Rational, Python tries B.__radd__ before
Rational.__add__. This is ok, because it was
implemented with knowledge of Rational, so it can
3. If B <: Fraction, Python tries B.__radd__ before
Fraction.__add__. This is ok, because it was
implemented with knowledge of Fraction, so it can
handle those instances before delegating to Real or
Complex.
The next two situations describe 'b + r'. We assume that b
didn't know about Rational in its implementation, and that it
didn't know about Fraction in its implementation, and that it
uses similar boilerplate code:
4. If B <: RationalAbc, then __radd_ converts both to the
4. If B <: Rational, then __radd_ converts both to the
builtin rational type (hey look, that's us) and
proceeds.
5. Otherwise, __radd__ tries to find the nearest common
@ -277,7 +277,7 @@ class Rational(RationalAbc):
"""
def forward(a, b):
if isinstance(b, (int, long, Rational)):
if isinstance(b, (int, long, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@ -289,7 +289,7 @@ class Rational(RationalAbc):
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
if isinstance(a, RationalAbc):
if isinstance(a, Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@ -305,7 +305,7 @@ class Rational(RationalAbc):
def _add(a, b):
"""a + b"""
return Rational(a.numerator * b.denominator +
return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)
@ -313,7 +313,7 @@ class Rational(RationalAbc):
def _sub(a, b):
"""a - b"""
return Rational(a.numerator * b.denominator -
return Fraction(a.numerator * b.denominator -
b.numerator * a.denominator,
a.denominator * b.denominator)
@ -321,13 +321,13 @@ class Rational(RationalAbc):
def _mul(a, b):
"""a * b"""
return Rational(a.numerator * b.numerator, a.denominator * b.denominator)
return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
__mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
def _div(a, b):
"""a / b"""
return Rational(a.numerator * b.denominator,
return Fraction(a.numerator * b.denominator,
a.denominator * b.numerator)
__truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
@ -337,7 +337,7 @@ class Rational(RationalAbc):
"""a // b"""
# Will be math.floor(a / b) in 3.0.
div = a / b
if isinstance(div, RationalAbc):
if isinstance(div, Rational):
# trunc(math.floor(div)) doesn't work if the rational is
# more precise than a float because the intermediate
# rounding may cross an integer boundary.
@ -349,7 +349,7 @@ class Rational(RationalAbc):
"""a // b"""
# Will be math.floor(a / b) in 3.0.
div = a / b
if isinstance(div, RationalAbc):
if isinstance(div, Rational):
# trunc(math.floor(div)) doesn't work if the rational is
# more precise than a float because the intermediate
# rounding may cross an integer boundary.
@ -375,14 +375,14 @@ class Rational(RationalAbc):
result will be rational.
"""
if isinstance(b, RationalAbc):
if isinstance(b, Rational):
if b.denominator == 1:
power = b.numerator
if power >= 0:
return Rational(a.numerator ** power,
return Fraction(a.numerator ** power,
a.denominator ** power)
else:
return Rational(a.denominator ** -power,
return Fraction(a.denominator ** -power,
a.numerator ** -power)
else:
# A fractional power will generally produce an
@ -397,8 +397,8 @@ class Rational(RationalAbc):
# If a is an int, keep it that way if possible.
return a ** b.numerator
if isinstance(a, RationalAbc):
return Rational(a.numerator, a.denominator) ** b
if isinstance(a, Rational):
return Fraction(a.numerator, a.denominator) ** b
if b.denominator == 1:
return a ** b.numerator
@ -406,16 +406,16 @@ class Rational(RationalAbc):
return a ** float(b)
def __pos__(a):
"""+a: Coerces a subclass instance to Rational"""
return Rational(a.numerator, a.denominator)
"""+a: Coerces a subclass instance to Fraction"""
return Fraction(a.numerator, a.denominator)
def __neg__(a):
"""-a"""
return Rational(-a.numerator, a.denominator)
return Fraction(-a.numerator, a.denominator)
def __abs__(a):
"""abs(a)"""
return Rational(abs(a.numerator), a.denominator)
return Fraction(abs(a.numerator), a.denominator)
def __trunc__(a):
"""trunc(a)"""
@ -445,7 +445,7 @@ class Rational(RationalAbc):
def __eq__(a, b):
"""a == b"""
if isinstance(b, RationalAbc):
if isinstance(b, Rational):
return (a.numerator == b.numerator and
a.denominator == b.denominator)
if isinstance(b, numbers.Complex) and b.imag == 0:
@ -472,7 +472,7 @@ class Rational(RationalAbc):
if isinstance(b, float):
b = a.from_float(b)
try:
# XXX: If b <: Real but not <: RationalAbc, this is likely
# XXX: If b <: Real but not <: Rational, this is likely
# to fall back to a float. If the actual values differ by
# less than MIN_FLOAT, this could falsely call them equal,
# which would make <= inconsistent with ==. Better ways of
@ -480,7 +480,7 @@ class Rational(RationalAbc):
diff = a - b
except TypeError:
return NotImplemented
if isinstance(diff, RationalAbc):
if isinstance(diff, Rational):
return op(diff.numerator, 0)
return op(diff, 0)
@ -510,11 +510,11 @@ class Rational(RationalAbc):
return (self.__class__, (str(self),))
def __copy__(self):
if type(self) == Rational:
if type(self) == Fraction:
return self # I'm immutable; therefore I am my own clone
return self.__class__(self.numerator, self.denominator)
def __deepcopy__(self, memo):
if type(self) == Rational:
if type(self) == Fraction:
return self # My components are also immutable
return self.__class__(self.numerator, self.denominator)

View File

@ -5,7 +5,7 @@ from test.test_support import fcmp, have_unicode, TESTFN, unlink, \
run_unittest, run_with_locale
from operator import neg
import sys, warnings, cStringIO, random, rational, UserDict
import sys, warnings, cStringIO, random, fractions, UserDict
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
FutureWarning, __name__)
warnings.filterwarnings("ignore", "integer argument expected",
@ -703,7 +703,7 @@ class BuiltinTest(unittest.TestCase):
n, d = f.as_integer_ratio()
self.assertEqual(float(n).__truediv__(d), f)
R = rational.Rational
R = fractions.Fraction
self.assertEqual(R(0, 1),
R(*float(0.0).as_integer_ratio()))
self.assertEqual(R(5, 2),

View File

@ -1,15 +1,15 @@
"""Tests for Lib/rational.py."""
"""Tests for Lib/fractions.py."""
from decimal import Decimal
from test.test_support import run_unittest, verbose
import math
import operator
import rational
import fractions
import unittest
from copy import copy, deepcopy
from cPickle import dumps, loads
R = rational.Rational
gcd = rational.gcd
R = fractions.Fraction
gcd = fractions.gcd
class GcdTest(unittest.TestCase):
@ -31,7 +31,7 @@ def _components(r):
return (r.numerator, r.denominator)
class RationalTest(unittest.TestCase):
class FractionTest(unittest.TestCase):
def assertTypedEquals(self, expected, actual):
"""Asserts that both the types and values are the same."""
@ -60,7 +60,7 @@ class RationalTest(unittest.TestCase):
self.assertEquals((7, 15), _components(R(7, 15)))
self.assertEquals((10**23, 1), _components(R(10**23)))
self.assertRaisesMessage(ZeroDivisionError, "Rational(12, 0)",
self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
R, 12, 0)
self.assertRaises(TypeError, R, 1.5)
self.assertRaises(TypeError, R, 1.5 + 3j)
@ -83,41 +83,41 @@ class RationalTest(unittest.TestCase):
self.assertRaisesMessage(
ZeroDivisionError, "Rational(3, 0)",
ZeroDivisionError, "Fraction(3, 0)",
R, "3/0")
self.assertRaisesMessage(
ValueError, "Invalid literal for Rational: 3/",
ValueError, "Invalid literal for Fraction: 3/",
R, "3/")
self.assertRaisesMessage(
ValueError, "Invalid literal for Rational: 3 /2",
ValueError, "Invalid literal for Fraction: 3 /2",
R, "3 /2")
self.assertRaisesMessage(
# Denominators don't need a sign.
ValueError, "Invalid literal for Rational: 3/+2",
ValueError, "Invalid literal for Fraction: 3/+2",
R, "3/+2")
self.assertRaisesMessage(
# Imitate float's parsing.
ValueError, "Invalid literal for Rational: + 3/2",
ValueError, "Invalid literal for Fraction: + 3/2",
R, "+ 3/2")
self.assertRaisesMessage(
# Avoid treating '.' as a regex special character.
ValueError, "Invalid literal for Rational: 3a2",
ValueError, "Invalid literal for Fraction: 3a2",
R, "3a2")
self.assertRaisesMessage(
# Only parse ordinary decimals, not scientific form.
ValueError, "Invalid literal for Rational: 3.2e4",
ValueError, "Invalid literal for Fraction: 3.2e4",
R, "3.2e4")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Rational: 3/7.2",
# Don't accept combinations of decimals and fractions.
ValueError, "Invalid literal for Fraction: 3/7.2",
R, "3/7.2")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Rational: 3.2/7",
# Don't accept combinations of decimals and fractions.
ValueError, "Invalid literal for Fraction: 3.2/7",
R, "3.2/7")
self.assertRaisesMessage(
# Allow 3. and .3, but not .
ValueError, "Invalid literal for Rational: .",
ValueError, "Invalid literal for Fraction: .",
R, ".")
def testImmutable(self):
@ -138,7 +138,7 @@ class RationalTest(unittest.TestCase):
def testFromFloat(self):
self.assertRaisesMessage(
TypeError, "Rational.from_float() only takes floats, not 3 (int)",
TypeError, "Fraction.from_float() only takes floats, not 3 (int)",
R.from_float, 3)
self.assertEquals((0, 1), _components(R.from_float(-0.0)))
@ -154,19 +154,19 @@ class RationalTest(unittest.TestCase):
inf = 1e1000
nan = inf - inf
self.assertRaisesMessage(
TypeError, "Cannot convert inf to Rational.",
TypeError, "Cannot convert inf to Fraction.",
R.from_float, inf)
self.assertRaisesMessage(
TypeError, "Cannot convert -inf to Rational.",
TypeError, "Cannot convert -inf to Fraction.",
R.from_float, -inf)
self.assertRaisesMessage(
TypeError, "Cannot convert nan to Rational.",
TypeError, "Cannot convert nan to Fraction.",
R.from_float, nan)
def testFromDecimal(self):
self.assertRaisesMessage(
TypeError,
"Rational.from_decimal() only takes Decimals, not 3 (int)",
"Fraction.from_decimal() only takes Decimals, not 3 (int)",
R.from_decimal, 3)
self.assertEquals(R(0), R.from_decimal(Decimal("-0")))
self.assertEquals(R(5, 10), R.from_decimal(Decimal("0.5")))
@ -176,16 +176,16 @@ class RationalTest(unittest.TestCase):
R.from_decimal(Decimal("0." + "9" * 30)))
self.assertRaisesMessage(
TypeError, "Cannot convert Infinity to Rational.",
TypeError, "Cannot convert Infinity to Fraction.",
R.from_decimal, Decimal("inf"))
self.assertRaisesMessage(
TypeError, "Cannot convert -Infinity to Rational.",
TypeError, "Cannot convert -Infinity to Fraction.",
R.from_decimal, Decimal("-inf"))
self.assertRaisesMessage(
TypeError, "Cannot convert NaN to Rational.",
TypeError, "Cannot convert NaN to Fraction.",
R.from_decimal, Decimal("nan"))
self.assertRaisesMessage(
TypeError, "Cannot convert sNaN to Rational.",
TypeError, "Cannot convert sNaN to Fraction.",
R.from_decimal, Decimal("snan"))
def testFromContinuedFraction(self):
@ -301,7 +301,7 @@ class RationalTest(unittest.TestCase):
# Decimal refuses mixed comparisons.
self.assertRaisesMessage(
TypeError,
"unsupported operand type(s) for +: 'Rational' and 'Decimal'",
"unsupported operand type(s) for +: 'Fraction' and 'Decimal'",
operator.add, R(3,11), Decimal('3.1415926'))
self.assertNotEquals(R(5, 2), Decimal('2.5'))
@ -363,7 +363,7 @@ class RationalTest(unittest.TestCase):
self.assertFalse(R(5, 2) == 2)
def testStringification(self):
self.assertEquals("Rational(7,3)", repr(R(7, 3)))
self.assertEquals("Fraction(7,3)", repr(R(7, 3)))
self.assertEquals("7/3", str(R(7, 3)))
self.assertEquals("7", str(R(7, 1)))
@ -406,7 +406,7 @@ class RationalTest(unittest.TestCase):
self.assertEqual(id(r), id(deepcopy(r)))
def test_main():
run_unittest(RationalTest, GcdTest)
run_unittest(FractionTest, GcdTest)
if __name__ == '__main__':
test_main()

View File

@ -400,6 +400,10 @@ Core and builtins
Library
-------
- Rename rational.py to fractions.py and the rational.Rational class
to fractions.Fraction, to avoid the name clash with the abstract
base class numbers.Rational. See discussion in issue #1682.
- The pickletools module now provides an optimize() function
that eliminates unused PUT opcodes from a pickle string.