summaryrefslogtreecommitdiffstats
path: root/Lib/rational.py
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@gmail.com>2008-01-27 23:08:46 (GMT)
committerJeffrey Yasskin <jyasskin@gmail.com>2008-01-27 23:08:46 (GMT)
commit3ea7b41b5805c60a05e697211d0bfc14a62a19fb (patch)
tree48fdcdbf67360b87d22314bca19599558b5d7e28 /Lib/rational.py
parent56eadd9d0d37d53f530f98878e77786743bebb0f (diff)
downloadcpython-3ea7b41b5805c60a05e697211d0bfc14a62a19fb.zip
cpython-3ea7b41b5805c60a05e697211d0bfc14a62a19fb.tar.gz
cpython-3ea7b41b5805c60a05e697211d0bfc14a62a19fb.tar.bz2
Moved Rational._binary_float_to_ratio() to float.as_integer_ratio() because
it's useful outside of rational numbers. This is my first C code that had to do anything significant. Please be more careful when looking over it.
Diffstat (limited to 'Lib/rational.py')
-rwxr-xr-xLib/rational.py56
1 files changed, 1 insertions, 55 deletions
diff --git a/Lib/rational.py b/Lib/rational.py
index 8ee38ba..99c5ff6 100755
--- a/Lib/rational.py
+++ b/Lib/rational.py
@@ -25,60 +25,6 @@ def gcd(a, b):
return a
-def _binary_float_to_ratio(x):
- """x -> (top, bot), a pair of ints s.t. x = top/bot.
-
- The conversion is done exactly, without rounding.
- bot > 0 guaranteed.
- Some form of binary fp is assumed.
- Pass NaNs or infinities at your own risk.
-
- >>> _binary_float_to_ratio(10.0)
- (10, 1)
- >>> _binary_float_to_ratio(0.0)
- (0, 1)
- >>> _binary_float_to_ratio(-.25)
- (-1, 4)
- """
- # XXX Move this to floatobject.c with a name like
- # float.as_integer_ratio()
-
- if x == 0:
- return 0, 1
- f, e = math.frexp(x)
- signbit = 1
- if f < 0:
- f = -f
- signbit = -1
- assert 0.5 <= f < 1.0
- # x = signbit * f * 2**e exactly
-
- # Suck up CHUNK bits at a time; 28 is enough so that we suck
- # up all bits in 2 iterations for all known binary double-
- # precision formats, and small enough to fit in an int.
- CHUNK = 28
- top = 0
- # invariant: x = signbit * (top + f) * 2**e exactly
- while f:
- f = math.ldexp(f, CHUNK)
- digit = trunc(f)
- assert digit >> CHUNK == 0
- top = (top << CHUNK) | digit
- f = f - digit
- assert 0.0 <= f < 1.0
- e = e - CHUNK
- assert top
-
- # Add in the sign bit.
- top = signbit * top
-
- # now x = top * 2**e exactly; fold in 2**e
- if e>0:
- return (top * 2**e, 1)
- else:
- return (top, 2 ** -e)
-
-
_RATIONAL_FORMAT = re.compile(
r'^\s*(?P<sign>[-+]?)(?P<num>\d+)'
r'(?:/(?P<denom>\d+)|\.(?P<decimal>\d+))?\s*$')
@@ -163,7 +109,7 @@ class Rational(RationalAbc):
(cls.__name__, f, type(f).__name__))
if math.isnan(f) or math.isinf(f):
raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
- return cls(*_binary_float_to_ratio(f))
+ return cls(*f.as_integer_ratio())
@classmethod
def from_decimal(cls, dec):