[Python-checkins] cpython: Issue #25971: Optimized creating Fractions from floats by 2 times and from

serhiy.storchaka python-checkins at python.org
Tue Dec 29 15:34:44 EST 2015


https://hg.python.org/cpython/rev/284026a8af9e
changeset: 99716:284026a8af9e
user: Serhiy Storchaka <storchaka at gmail.com>
date: Tue Dec 29 22:34:23 2015 +0200
summary:
 Issue #25971: Optimized creating Fractions from floats by 2 times and from
Decimals by 3 times.
Unified error messages in float.as_integer_ratio(), Decimal.as_integer_ratio(),
and Fraction constructors.
files:
 Lib/_pydecimal.py | 6 +---
 Lib/fractions.py | 32 +++----------------------
 Lib/test/test_fractions.py | 14 +++++-----
 Misc/NEWS | 3 ++
 Objects/floatobject.c | 12 ++++----
 5 files changed, 22 insertions(+), 45 deletions(-)
diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py
--- a/Lib/_pydecimal.py
+++ b/Lib/_pydecimal.py
@@ -1026,11 +1026,9 @@
 """
 if self._is_special:
 if self.is_nan():
- raise ValueError("Cannot pass NaN "
- "to decimal.as_integer_ratio.")
+ raise ValueError("cannot convert NaN to integer ratio")
 else:
- raise OverflowError("Cannot pass infinity "
- "to decimal.as_integer_ratio.")
+ raise OverflowError("cannot convert Infinity to integer ratio")
 
 if not self:
 return 0, 1
diff --git a/Lib/fractions.py b/Lib/fractions.py
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -125,17 +125,9 @@
 self._denominator = numerator.denominator
 return self
 
- elif isinstance(numerator, float):
- # Exact conversion from float
- value = Fraction.from_float(numerator)
- self._numerator = value._numerator
- self._denominator = value._denominator
- return self
-
- elif isinstance(numerator, Decimal):
- value = Fraction.from_decimal(numerator)
- self._numerator = value._numerator
- self._denominator = value._denominator
+ elif isinstance(numerator, (float, Decimal)):
+ # Exact conversion
+ self._numerator, self._denominator = numerator.as_integer_ratio()
 return self
 
 elif isinstance(numerator, str):
@@ -210,10 +202,6 @@
 elif not isinstance(f, float):
 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
 (cls.__name__, f, type(f).__name__))
- if math.isnan(f):
- raise ValueError("Cannot convert %r to %s." % (f, cls.__name__))
- if math.isinf(f):
- raise OverflowError("Cannot convert %r to %s." % (f, cls.__name__))
 return cls(*f.as_integer_ratio())
 
 @classmethod
@@ -226,19 +214,7 @@
 raise TypeError(
 "%s.from_decimal() only takes Decimals, not %r (%s)" %
 (cls.__name__, dec, type(dec).__name__))
- if dec.is_infinite():
- raise OverflowError(
- "Cannot convert %s to %s." % (dec, cls.__name__))
- if dec.is_nan():
- raise ValueError("Cannot convert %s to %s." % (dec, cls.__name__))
- sign, digits, exp = dec.as_tuple()
- digits = int(''.join(map(str, digits)))
- if sign:
- digits = -digits
- if exp >= 0:
- return cls(digits * 10 ** exp)
- else:
- return cls(digits, 10 ** -exp)
+ return cls(*dec.as_integer_ratio())
 
 def limit_denominator(self, max_denominator=1000000):
 """Closest Fraction to self with denominator at most max_denominator.
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
@@ -263,13 +263,13 @@
 nan = inf - inf
 # bug 16469: error types should be consistent with float -> int
 self.assertRaisesMessage(
- OverflowError, "Cannot convert inf to Fraction.",
+ OverflowError, "cannot convert Infinity to integer ratio",
 F.from_float, inf)
 self.assertRaisesMessage(
- OverflowError, "Cannot convert -inf to Fraction.",
+ OverflowError, "cannot convert Infinity to integer ratio",
 F.from_float, -inf)
 self.assertRaisesMessage(
- ValueError, "Cannot convert nan to Fraction.",
+ ValueError, "cannot convert NaN to integer ratio",
 F.from_float, nan)
 
 def testFromDecimal(self):
@@ -284,16 +284,16 @@
 
 # bug 16469: error types should be consistent with decimal -> int
 self.assertRaisesMessage(
- OverflowError, "Cannot convert Infinity to Fraction.",
+ OverflowError, "cannot convert Infinity to integer ratio",
 F.from_decimal, Decimal("inf"))
 self.assertRaisesMessage(
- OverflowError, "Cannot convert -Infinity to Fraction.",
+ OverflowError, "cannot convert Infinity to integer ratio",
 F.from_decimal, Decimal("-inf"))
 self.assertRaisesMessage(
- ValueError, "Cannot convert NaN to Fraction.",
+ ValueError, "cannot convert NaN to integer ratio",
 F.from_decimal, Decimal("nan"))
 self.assertRaisesMessage(
- ValueError, "Cannot convert sNaN to Fraction.",
+ ValueError, "cannot convert NaN to integer ratio",
 F.from_decimal, Decimal("snan"))
 
 def testLimitDenominator(self):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -126,6 +126,9 @@
 Library
 -------
 
+- Issue #25971: Optimized creating Fractions from floats by 2 times and from
+ Decimals by 3 times.
+
 - Issue #25802: Document as deprecated the remaining implementations of
 importlib.abc.Loader.load_module().
 
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1466,14 +1466,14 @@
 CONVERT_TO_DOUBLE(v, self);
 
 if (Py_IS_INFINITY(self)) {
- PyErr_SetString(PyExc_OverflowError,
- "Cannot pass infinity to float.as_integer_ratio.");
- return NULL;
+ PyErr_SetString(PyExc_OverflowError,
+ "cannot convert Infinity to integer ratio");
+ return NULL;
 }
 if (Py_IS_NAN(self)) {
- PyErr_SetString(PyExc_ValueError,
- "Cannot pass NaN to float.as_integer_ratio.");
- return NULL;
+ PyErr_SetString(PyExc_ValueError,
+ "cannot convert NaN to integer ratio");
+ return NULL;
 }
 
 PyFPE_START_PROTECT("as_integer_ratio", goto error);
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /