[pypy-commit] pypy py3.6: Add Decimal.as_integer_ratio()

amauryfa pypy.commits at gmail.com
Mon Dec 11 17:18:59 EST 2017


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.6
Changeset: r93375:5b8174a4dd1d
Date: 2017-12-11 19:47 +0100
http://bitbucket.org/pypy/pypy/changeset/5b8174a4dd1d/

Log:	Add Decimal.as_integer_ratio()

diff --git a/lib_pypy/_decimal.py b/lib_pypy/_decimal.py
--- a/lib_pypy/_decimal.py
+++ b/lib_pypy/_decimal.py
@@ -448,6 +448,36 @@
 
         return DecimalTuple(sign, coeff, expt)
 
+    def as_integer_ratio(self):
+        "Convert a Decimal to its exact integer ratio representation"
+        if _mpdec.mpd_isspecial(self._mpd):
+            if _mpdec.mpd_isnan(self._mpd):
+                raise ValueError("cannot convert NaN to integer ratio")
+            else:
+                raise OverflowError("cannot convert Infinity to integer ratio")
+
+        context = getcontext()
+        tmp = Decimal._new_empty()
+        with _CatchStatus(context) as (ctx, status_ptr):
+            _mpdec.mpd_qcopy(tmp._mpd, self._mpd, status_ptr)
+        exp = tmp._mpd.exp if tmp else 0
+        tmp._mpd.exp = 0
+
+        # context and rounding are unused here: the conversion is exact
+        numerator = tmp._to_int(_mpdec.MPD_ROUND_FLOOR)
+
+        exponent = 10 ** abs(exp)
+        if exp >= 0:
+            numerator *= exponent
+            denominator = 1
+        else:
+            denominator = exponent
+            gcd = _math.gcd(numerator, denominator)
+            numerator //= gcd
+            denominator //= gcd
+
+        return numerator, denominator
+
     def _convert_for_comparison(self, other, op):
         if isinstance(other, Decimal):
             return self, other


More information about the pypy-commit mailing list