[Python-checkins] cpython: Issue #21136: Avoid unnecessary normalization in Fractions resulting from power
mark.dickinson
python-checkins at python.org
Sat Apr 5 10:29:17 CEST 2014
http://hg.python.org/cpython/rev/91d7fadac271
changeset: 90152:91d7fadac271
user: Mark Dickinson <dickinsm at gmail.com>
date: Sat Apr 05 09:29:00 2014 +0100
summary:
Issue #21136: Avoid unnecessary normalization in Fractions resulting from power and other operations.
files:
Lib/fractions.py | 23 ++++++++++++++---------
Lib/test/test_fractions.py | 3 ++-
Misc/NEWS | 3 +++
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/Lib/fractions.py b/Lib/fractions.py
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -70,7 +70,7 @@
__slots__ = ('_numerator', '_denominator')
# We're immutable, so use __new__ not __init__
- def __new__(cls, numerator=0, denominator=None):
+ def __new__(cls, numerator=0, denominator=None, _normalize=True):
"""Constructs a Rational.
Takes a string like '3/2' or '1.5', another Rational instance, a
@@ -165,9 +165,12 @@
if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
- g = gcd(numerator, denominator)
- self._numerator = numerator // g
- self._denominator = denominator // g
+ if _normalize:
+ g = gcd(numerator, denominator)
+ numerator //= g
+ denominator //= g
+ self._numerator = numerator
+ self._denominator = denominator
return self
@classmethod
@@ -453,10 +456,12 @@
power = b.numerator
if power >= 0:
return Fraction(a._numerator ** power,
- a._denominator ** power)
+ a._denominator ** power,
+ _normalize=False)
else:
return Fraction(a._denominator ** -power,
- a._numerator ** -power)
+ a._numerator ** -power,
+ _normalize=False)
else:
# A fractional power will generally produce an
# irrational number.
@@ -480,15 +485,15 @@
def __pos__(a):
"""+a: Coerces a subclass instance to Fraction"""
- return Fraction(a._numerator, a._denominator)
+ return Fraction(a._numerator, a._denominator, _normalize=False)
def __neg__(a):
"""-a"""
- return Fraction(-a._numerator, a._denominator)
+ return Fraction(-a._numerator, a._denominator, _normalize=False)
def __abs__(a):
"""abs(a)"""
- return Fraction(abs(a._numerator), a._denominator)
+ return Fraction(abs(a._numerator), a._denominator, _normalize=False)
def __trunc__(a):
"""trunc(a)"""
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -330,7 +330,6 @@
self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
-
def testArithmetic(self):
self.assertEqual(F(1, 2), F(1, 10) + F(2, 5))
self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5))
@@ -402,6 +401,8 @@
self.assertTypedEquals(2.0 , 4 ** F(1, 2))
self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
+ self.assertRaises(ZeroDivisionError, operator.pow,
+ F(0, 1), -2)
def testMixingWithDecimal(self):
# Decimal refuses mixed arithmetic (but not mixed comparisons)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -29,6 +29,9 @@
Library
-------
+- Issue #21136: Avoid unnecessary normalization of Fractions resulting from
+ power and other operations. Patch by Raymond Hettinger.
+
- Issue #17621: Introduce importlib.util.LazyLoader.
- Issue #21076: signal module constants were turned into enums.
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list