blob: 446ad8ea8279a1c754c1055e0b2c411731861fcb [file] [log] [blame]
Jeffrey Yasskind7b00332008-01-15 07:46:24 +00001# Originally contributed by Sjoerd Mullender.
2# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
3
4"""Rational, infinite-precision, real numbers."""
5
6from __future__ import division
7import math
8import numbers
9import operator
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000010import re
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000011
Raymond Hettingercf98f032008-05-08 04:36:12 +000012__all__ = ['Fraction', 'gcd']
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000013
Mark Dickinsond058cd22008-02-10 21:29:51 +000014Rational = numbers.Rational
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000015
16
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +000017def gcd(a, b):
18 """Calculate the Greatest Common Divisor of a and b.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000019
20 Unless b==0, the result will have the same sign as b (so that when
21 b is divided by it, the result comes out positive).
22 """
23 while b:
24 a, b = b, a%b
25 return a
26
27
Mark Dickinson1dabdb22008-02-02 17:16:13 +000028_RATIONAL_FORMAT = re.compile(r"""
29 \A\s* # optional whitespace at the start, then
30 (?P<sign>[-+]?) # an optional sign, then
31 (?=\d|\.\d) # lookahead for digit or .digit
32 (?P<num>\d*) # numerator (possibly empty)
33 (?: # followed by an optional
34 /(?P<denom>\d+) # / and denominator
35 | # or
36 \.(?P<decimal>\d*) # decimal point and fractional part
37 )?
38 \s*\Z # and optional whitespace to finish
39""", re.VERBOSE)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000040
41
Mark Dickinsond058cd22008-02-10 21:29:51 +000042class Fraction(Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000043 """This class implements rational numbers.
44
Mark Dickinsond058cd22008-02-10 21:29:51 +000045 Fraction(8, 6) will produce a rational number equivalent to
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000046 4/3. Both arguments must be Integral. The numerator defaults to 0
Mark Dickinsond058cd22008-02-10 21:29:51 +000047 and the denominator defaults to 1 so that Fraction(3) == 3 and
48 Fraction() == 0.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000049
Mark Dickinsond058cd22008-02-10 21:29:51 +000050 Fractions can also be constructed from strings of the form
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +000051 '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000052
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000053 """
54
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +000055 __slots__ = ('_numerator', '_denominator')
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000056
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000057 # We're immutable, so use __new__ not __init__
58 def __new__(cls, numerator=0, denominator=1):
Mark Dickinsond058cd22008-02-10 21:29:51 +000059 """Constructs a Fraction.
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000060
Mark Dickinsond058cd22008-02-10 21:29:51 +000061 Takes a string like '3/2' or '1.5', another Fraction, or a
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +000062 numerator/denominator pair.
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000063
64 """
Mark Dickinsond058cd22008-02-10 21:29:51 +000065 self = super(Fraction, cls).__new__(cls)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000066
Jeffrey Yasskin1c214d62008-02-14 06:12:24 +000067 if type(numerator) not in (int, long) and denominator == 1:
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000068 if isinstance(numerator, basestring):
69 # Handle construction from strings.
70 input = numerator
71 m = _RATIONAL_FORMAT.match(input)
72 if m is None:
Andrew M. Kuchlingf4843632008-06-21 13:47:20 +000073 raise ValueError('Invalid literal for Fraction: %r' % input)
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +000074 numerator = m.group('num')
75 decimal = m.group('decimal')
76 if decimal:
77 # The literal is a decimal number.
78 numerator = int(numerator + decimal)
79 denominator = 10**len(decimal)
80 else:
81 # The literal is an integer or fraction.
82 numerator = int(numerator)
83 # Default denominator to 1.
84 denominator = int(m.group('denom') or 1)
85
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000086 if m.group('sign') == '-':
87 numerator = -numerator
88
Jeffrey Yasskin1c214d62008-02-14 06:12:24 +000089 elif isinstance(numerator, Rational):
90 # Handle copies from other rationals. Integrals get
91 # caught here too, but it doesn't matter because
92 # denominator is already 1.
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000093 other_rational = numerator
94 numerator = other_rational.numerator
95 denominator = other_rational.denominator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000096
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000097 if denominator == 0:
Mark Dickinsond058cd22008-02-10 21:29:51 +000098 raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
Raymond Hettinger548db582008-07-10 10:28:41 +000099 numerator = operator.index(numerator)
100 denominator = operator.index(denominator)
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +0000101 g = gcd(numerator, denominator)
Jeffrey Yasskin1c214d62008-02-14 06:12:24 +0000102 self._numerator = numerator // g
103 self._denominator = denominator // g
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000104 return self
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000105
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000106 @classmethod
107 def from_float(cls, f):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000108 """Converts a finite float to a rational number, exactly.
109
Mark Dickinsond058cd22008-02-10 21:29:51 +0000110 Beware that Fraction.from_float(0.3) != Fraction(3, 10).
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000111
112 """
Raymond Hettingerb01713e2008-07-10 14:34:57 +0000113 if isinstance(f, numbers.Integral):
Georg Brandlfe427892009-01-03 22:03:11 +0000114 return cls(f)
Raymond Hettingerb01713e2008-07-10 14:34:57 +0000115 elif not isinstance(f, float):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000116 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
117 (cls.__name__, f, type(f).__name__))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000118 if math.isnan(f) or math.isinf(f):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000119 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
120 return cls(*f.as_integer_ratio())
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000121
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000122 @classmethod
123 def from_decimal(cls, dec):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000124 """Converts a finite Decimal instance to a rational number, exactly."""
125 from decimal import Decimal
Raymond Hettingerb01713e2008-07-10 14:34:57 +0000126 if isinstance(dec, numbers.Integral):
127 dec = Decimal(int(dec))
128 elif not isinstance(dec, Decimal):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000129 raise TypeError(
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000130 "%s.from_decimal() only takes Decimals, not %r (%s)" %
131 (cls.__name__, dec, type(dec).__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000132 if not dec.is_finite():
133 # Catches infinities and nans.
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000134 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000135 sign, digits, exp = dec.as_tuple()
136 digits = int(''.join(map(str, digits)))
137 if sign:
138 digits = -digits
139 if exp >= 0:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000140 return cls(digits * 10 ** exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000141 else:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000142 return cls(digits, 10 ** -exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000143
Mark Dickinsone1b82472008-02-12 21:31:59 +0000144 def limit_denominator(self, max_denominator=1000000):
145 """Closest Fraction to self with denominator at most max_denominator.
Raymond Hettingercf109262008-01-24 00:54:21 +0000146
Mark Dickinsone1b82472008-02-12 21:31:59 +0000147 >>> Fraction('3.141592653589793').limit_denominator(10)
148 Fraction(22, 7)
149 >>> Fraction('3.141592653589793').limit_denominator(100)
150 Fraction(311, 99)
151 >>> Fraction(1234, 5678).limit_denominator(10000)
152 Fraction(1234, 5678)
Raymond Hettingercf109262008-01-24 00:54:21 +0000153
Mark Dickinsone1b82472008-02-12 21:31:59 +0000154 """
155 # Algorithm notes: For any real number x, define a *best upper
156 # approximation* to x to be a rational number p/q such that:
157 #
158 # (1) p/q >= x, and
159 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
160 #
161 # Define *best lower approximation* similarly. Then it can be
162 # proved that a rational number is a best upper or lower
163 # approximation to x if, and only if, it is a convergent or
164 # semiconvergent of the (unique shortest) continued fraction
165 # associated to x.
166 #
167 # To find a best rational approximation with denominator <= M,
168 # we find the best upper and lower approximations with
169 # denominator <= M and take whichever of these is closer to x.
170 # In the event of a tie, the bound with smaller denominator is
171 # chosen. If both denominators are equal (which can happen
172 # only when max_denominator == 1 and self is midway between
173 # two integers) the lower bound---i.e., the floor of self, is
174 # taken.
175
176 if max_denominator < 1:
177 raise ValueError("max_denominator should be at least 1")
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000178 if self._denominator <= max_denominator:
Mark Dickinsone1b82472008-02-12 21:31:59 +0000179 return Fraction(self)
180
181 p0, q0, p1, q1 = 0, 1, 1, 0
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000182 n, d = self._numerator, self._denominator
Mark Dickinsone1b82472008-02-12 21:31:59 +0000183 while True:
184 a = n//d
185 q2 = q0+a*q1
186 if q2 > max_denominator:
Raymond Hettingercf109262008-01-24 00:54:21 +0000187 break
Mark Dickinsone1b82472008-02-12 21:31:59 +0000188 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
189 n, d = d, n-a*d
190
191 k = (max_denominator-q0)//q1
192 bound1 = Fraction(p0+k*p1, q0+k*q1)
193 bound2 = Fraction(p1, q1)
194 if abs(bound2 - self) <= abs(bound1-self):
195 return bound2
196 else:
197 return bound1
Raymond Hettingercf109262008-01-24 00:54:21 +0000198
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +0000199 @property
200 def numerator(a):
201 return a._numerator
202
203 @property
204 def denominator(a):
205 return a._denominator
206
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000207 def __repr__(self):
208 """repr(self)"""
Mark Dickinson3af386a2008-06-27 10:11:52 +0000209 return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000210
211 def __str__(self):
212 """str(self)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000213 if self._denominator == 1:
214 return str(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000215 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000216 return '%s/%s' % (self._numerator, self._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000217
218 def _operator_fallbacks(monomorphic_operator, fallback_operator):
219 """Generates forward and reverse operators given a purely-rational
220 operator and a function from the operator module.
221
222 Use this like:
223 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
224
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000225 In general, we want to implement the arithmetic operations so
226 that mixed-mode operations either call an implementation whose
227 author knew about the types of both arguments, or convert both
228 to the nearest built in type and do the operation there. In
Mark Dickinsond058cd22008-02-10 21:29:51 +0000229 Fraction, that means that we define __add__ and __radd__ as:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000230
231 def __add__(self, other):
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000232 # Both types have numerators/denominator attributes,
233 # so do the operation directly
Mark Dickinsond058cd22008-02-10 21:29:51 +0000234 if isinstance(other, (int, long, Fraction)):
235 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000236 other.numerator * self.denominator,
237 self.denominator * other.denominator)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000238 # float and complex don't have those operations, but we
239 # know about those types, so special case them.
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000240 elif isinstance(other, float):
241 return float(self) + other
242 elif isinstance(other, complex):
243 return complex(self) + other
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000244 # Let the other type take over.
245 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000246
247 def __radd__(self, other):
248 # radd handles more types than add because there's
249 # nothing left to fall back to.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000250 if isinstance(other, Rational):
251 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000252 other.numerator * self.denominator,
253 self.denominator * other.denominator)
254 elif isinstance(other, Real):
255 return float(other) + float(self)
256 elif isinstance(other, Complex):
257 return complex(other) + complex(self)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000258 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000259
260
261 There are 5 different cases for a mixed-type addition on
Mark Dickinsond058cd22008-02-10 21:29:51 +0000262 Fraction. I'll refer to all of the above code that doesn't
263 refer to Fraction, float, or complex as "boilerplate". 'r'
264 will be an instance of Fraction, which is a subtype of
265 Rational (r : Fraction <: Rational), and b : B <:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000266 Complex. The first three involve 'r + b':
267
Mark Dickinsond058cd22008-02-10 21:29:51 +0000268 1. If B <: Fraction, int, float, or complex, we handle
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000269 that specially, and all is well.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000270 2. If Fraction falls back to the boilerplate code, and it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000271 were to return a value from __add__, we'd miss the
272 possibility that B defines a more intelligent __radd__,
273 so the boilerplate should return NotImplemented from
Mark Dickinsond058cd22008-02-10 21:29:51 +0000274 __add__. In particular, we don't handle Rational
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000275 here, even though we could get an exact answer, in case
276 the other type wants to do something special.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000277 3. If B <: Fraction, Python tries B.__radd__ before
278 Fraction.__add__. This is ok, because it was
279 implemented with knowledge of Fraction, so it can
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000280 handle those instances before delegating to Real or
281 Complex.
282
283 The next two situations describe 'b + r'. We assume that b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000284 didn't know about Fraction in its implementation, and that it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000285 uses similar boilerplate code:
286
Mark Dickinsond058cd22008-02-10 21:29:51 +0000287 4. If B <: Rational, then __radd_ converts both to the
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000288 builtin rational type (hey look, that's us) and
289 proceeds.
290 5. Otherwise, __radd__ tries to find the nearest common
291 base ABC, and fall back to its builtin type. Since this
292 class doesn't subclass a concrete type, there's no
293 implementation to fall back to, so we need to try as
294 hard as possible to return an actual value, or the user
295 will get a TypeError.
296
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000297 """
298 def forward(a, b):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000299 if isinstance(b, (int, long, Fraction)):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000300 return monomorphic_operator(a, b)
301 elif isinstance(b, float):
302 return fallback_operator(float(a), b)
303 elif isinstance(b, complex):
304 return fallback_operator(complex(a), b)
305 else:
306 return NotImplemented
307 forward.__name__ = '__' + fallback_operator.__name__ + '__'
308 forward.__doc__ = monomorphic_operator.__doc__
309
310 def reverse(b, a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000311 if isinstance(a, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000312 # Includes ints.
313 return monomorphic_operator(a, b)
314 elif isinstance(a, numbers.Real):
315 return fallback_operator(float(a), float(b))
316 elif isinstance(a, numbers.Complex):
317 return fallback_operator(complex(a), complex(b))
318 else:
319 return NotImplemented
320 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
321 reverse.__doc__ = monomorphic_operator.__doc__
322
323 return forward, reverse
324
325 def _add(a, b):
326 """a + b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000327 return Fraction(a.numerator * b.denominator +
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000328 b.numerator * a.denominator,
329 a.denominator * b.denominator)
330
331 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
332
333 def _sub(a, b):
334 """a - b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000335 return Fraction(a.numerator * b.denominator -
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000336 b.numerator * a.denominator,
337 a.denominator * b.denominator)
338
339 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
340
341 def _mul(a, b):
342 """a * b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000343 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000344
345 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
346
347 def _div(a, b):
348 """a / b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000349 return Fraction(a.numerator * b.denominator,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000350 a.denominator * b.numerator)
351
352 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
353 __div__, __rdiv__ = _operator_fallbacks(_div, operator.div)
354
Raymond Hettinger909e3342008-01-24 23:50:26 +0000355 def __floordiv__(a, b):
356 """a // b"""
357 # Will be math.floor(a / b) in 3.0.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000358 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000359 if isinstance(div, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000360 # trunc(math.floor(div)) doesn't work if the rational is
361 # more precise than a float because the intermediate
362 # rounding may cross an integer boundary.
363 return div.numerator // div.denominator
364 else:
365 return math.floor(div)
366
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000367 def __rfloordiv__(b, a):
368 """a // b"""
369 # Will be math.floor(a / b) in 3.0.
Raymond Hettinger909e3342008-01-24 23:50:26 +0000370 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000371 if isinstance(div, Rational):
Raymond Hettinger909e3342008-01-24 23:50:26 +0000372 # trunc(math.floor(div)) doesn't work if the rational is
373 # more precise than a float because the intermediate
374 # rounding may cross an integer boundary.
375 return div.numerator // div.denominator
376 else:
377 return math.floor(div)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000378
379 def __mod__(a, b):
380 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000381 div = a // b
382 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000383
384 def __rmod__(b, a):
385 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000386 div = a // b
387 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000388
389 def __pow__(a, b):
390 """a ** b
391
392 If b is not an integer, the result will be a float or complex
393 since roots are generally irrational. If b is an integer, the
394 result will be rational.
395
396 """
Mark Dickinsond058cd22008-02-10 21:29:51 +0000397 if isinstance(b, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000398 if b.denominator == 1:
399 power = b.numerator
400 if power >= 0:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000401 return Fraction(a._numerator ** power,
402 a._denominator ** power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000403 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000404 return Fraction(a._denominator ** -power,
405 a._numerator ** -power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000406 else:
407 # A fractional power will generally produce an
408 # irrational number.
409 return float(a) ** float(b)
410 else:
411 return float(a) ** b
412
413 def __rpow__(b, a):
414 """a ** b"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000415 if b._denominator == 1 and b._numerator >= 0:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000416 # If a is an int, keep it that way if possible.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000417 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000418
Mark Dickinsond058cd22008-02-10 21:29:51 +0000419 if isinstance(a, Rational):
420 return Fraction(a.numerator, a.denominator) ** b
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000421
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000422 if b._denominator == 1:
423 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000424
425 return a ** float(b)
426
427 def __pos__(a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000428 """+a: Coerces a subclass instance to Fraction"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000429 return Fraction(a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000430
431 def __neg__(a):
432 """-a"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000433 return Fraction(-a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000434
435 def __abs__(a):
436 """abs(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000437 return Fraction(abs(a._numerator), a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000438
439 def __trunc__(a):
440 """trunc(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000441 if a._numerator < 0:
442 return -(-a._numerator // a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000443 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000444 return a._numerator // a._denominator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000445
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000446 def __hash__(self):
447 """hash(self)
448
449 Tricky because values that are exactly representable as a
450 float must have the same hash as that float.
451
452 """
Raymond Hettinger921cb5d2008-01-25 00:33:45 +0000453 # XXX since this method is expensive, consider caching the result
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000454 if self._denominator == 1:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000455 # Get integers right.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000456 return hash(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000457 # Expensive check, but definitely correct.
458 if self == float(self):
459 return hash(float(self))
460 else:
461 # Use tuple's hash to avoid a high collision rate on
462 # simple fractions.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000463 return hash((self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000464
465 def __eq__(a, b):
466 """a == b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000467 if isinstance(b, Rational):
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000468 return (a._numerator == b.numerator and
469 a._denominator == b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000470 if isinstance(b, numbers.Complex) and b.imag == 0:
471 b = b.real
472 if isinstance(b, float):
473 return a == a.from_float(b)
474 else:
475 # XXX: If b.__eq__ is implemented like this method, it may
476 # give the wrong answer after float(a) changes a's
477 # value. Better ways of doing this are welcome.
478 return float(a) == b
479
480 def _subtractAndCompareToZero(a, b, op):
481 """Helper function for comparison operators.
482
483 Subtracts b from a, exactly if possible, and compares the
484 result with 0 using op, in such a way that the comparison
485 won't recurse. If the difference raises a TypeError, returns
486 NotImplemented instead.
487
488 """
489 if isinstance(b, numbers.Complex) and b.imag == 0:
490 b = b.real
491 if isinstance(b, float):
492 b = a.from_float(b)
493 try:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000494 # XXX: If b <: Real but not <: Rational, this is likely
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000495 # to fall back to a float. If the actual values differ by
496 # less than MIN_FLOAT, this could falsely call them equal,
497 # which would make <= inconsistent with ==. Better ways of
498 # doing this are welcome.
499 diff = a - b
500 except TypeError:
501 return NotImplemented
Mark Dickinsond058cd22008-02-10 21:29:51 +0000502 if isinstance(diff, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000503 return op(diff.numerator, 0)
504 return op(diff, 0)
505
506 def __lt__(a, b):
507 """a < b"""
508 return a._subtractAndCompareToZero(b, operator.lt)
509
510 def __gt__(a, b):
511 """a > b"""
512 return a._subtractAndCompareToZero(b, operator.gt)
513
514 def __le__(a, b):
515 """a <= b"""
516 return a._subtractAndCompareToZero(b, operator.le)
517
518 def __ge__(a, b):
519 """a >= b"""
520 return a._subtractAndCompareToZero(b, operator.ge)
521
522 def __nonzero__(a):
523 """a != 0"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000524 return a._numerator != 0
Raymond Hettingera6216742008-01-25 00:21:54 +0000525
526 # support for pickling, copy, and deepcopy
527
528 def __reduce__(self):
529 return (self.__class__, (str(self),))
530
531 def __copy__(self):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000532 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000533 return self # I'm immutable; therefore I am my own clone
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000534 return self.__class__(self._numerator, self._denominator)
Raymond Hettingera6216742008-01-25 00:21:54 +0000535
536 def __deepcopy__(self, memo):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000537 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000538 return self # My components are also immutable
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000539 return self.__class__(self._numerator, self._denominator)