blob: 0d85f15d6cc9bdab291251c6290872ffc89d3833 [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:
Mark Dickinsond058cd22008-02-10 21:29:51 +000073 raise ValueError('Invalid literal for Fraction: ' + 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)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000099
Jeffrey Yasskin1c214d62008-02-14 06:12:24 +0000100 numerator = numerator.__index__()
101 denominator = denominator.__index__()
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +0000102 g = gcd(numerator, denominator)
Jeffrey Yasskin1c214d62008-02-14 06:12:24 +0000103 self._numerator = numerator // g
104 self._denominator = denominator // g
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000105 return self
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000106
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000107 @classmethod
108 def from_float(cls, f):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000109 """Converts a finite float to a rational number, exactly.
110
Mark Dickinsond058cd22008-02-10 21:29:51 +0000111 Beware that Fraction.from_float(0.3) != Fraction(3, 10).
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000112
113 """
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000114 if not isinstance(f, float):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000115 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
116 (cls.__name__, f, type(f).__name__))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000117 if math.isnan(f) or math.isinf(f):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000118 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
119 return cls(*f.as_integer_ratio())
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000120
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000121 @classmethod
122 def from_decimal(cls, dec):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000123 """Converts a finite Decimal instance to a rational number, exactly."""
124 from decimal import Decimal
125 if not isinstance(dec, Decimal):
126 raise TypeError(
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000127 "%s.from_decimal() only takes Decimals, not %r (%s)" %
128 (cls.__name__, dec, type(dec).__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000129 if not dec.is_finite():
130 # Catches infinities and nans.
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000131 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000132 sign, digits, exp = dec.as_tuple()
133 digits = int(''.join(map(str, digits)))
134 if sign:
135 digits = -digits
136 if exp >= 0:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000137 return cls(digits * 10 ** exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000138 else:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000139 return cls(digits, 10 ** -exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000140
Mark Dickinsone1b82472008-02-12 21:31:59 +0000141 def limit_denominator(self, max_denominator=1000000):
142 """Closest Fraction to self with denominator at most max_denominator.
Raymond Hettingercf109262008-01-24 00:54:21 +0000143
Mark Dickinsone1b82472008-02-12 21:31:59 +0000144 >>> Fraction('3.141592653589793').limit_denominator(10)
145 Fraction(22, 7)
146 >>> Fraction('3.141592653589793').limit_denominator(100)
147 Fraction(311, 99)
148 >>> Fraction(1234, 5678).limit_denominator(10000)
149 Fraction(1234, 5678)
Raymond Hettingercf109262008-01-24 00:54:21 +0000150
Mark Dickinsone1b82472008-02-12 21:31:59 +0000151 """
152 # Algorithm notes: For any real number x, define a *best upper
153 # approximation* to x to be a rational number p/q such that:
154 #
155 # (1) p/q >= x, and
156 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
157 #
158 # Define *best lower approximation* similarly. Then it can be
159 # proved that a rational number is a best upper or lower
160 # approximation to x if, and only if, it is a convergent or
161 # semiconvergent of the (unique shortest) continued fraction
162 # associated to x.
163 #
164 # To find a best rational approximation with denominator <= M,
165 # we find the best upper and lower approximations with
166 # denominator <= M and take whichever of these is closer to x.
167 # In the event of a tie, the bound with smaller denominator is
168 # chosen. If both denominators are equal (which can happen
169 # only when max_denominator == 1 and self is midway between
170 # two integers) the lower bound---i.e., the floor of self, is
171 # taken.
172
173 if max_denominator < 1:
174 raise ValueError("max_denominator should be at least 1")
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000175 if self._denominator <= max_denominator:
Mark Dickinsone1b82472008-02-12 21:31:59 +0000176 return Fraction(self)
177
178 p0, q0, p1, q1 = 0, 1, 1, 0
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000179 n, d = self._numerator, self._denominator
Mark Dickinsone1b82472008-02-12 21:31:59 +0000180 while True:
181 a = n//d
182 q2 = q0+a*q1
183 if q2 > max_denominator:
Raymond Hettingercf109262008-01-24 00:54:21 +0000184 break
Mark Dickinsone1b82472008-02-12 21:31:59 +0000185 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
186 n, d = d, n-a*d
187
188 k = (max_denominator-q0)//q1
189 bound1 = Fraction(p0+k*p1, q0+k*q1)
190 bound2 = Fraction(p1, q1)
191 if abs(bound2 - self) <= abs(bound1-self):
192 return bound2
193 else:
194 return bound1
Raymond Hettingercf109262008-01-24 00:54:21 +0000195
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +0000196 @property
197 def numerator(a):
198 return a._numerator
199
200 @property
201 def denominator(a):
202 return a._denominator
203
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000204 def __repr__(self):
205 """repr(self)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000206 return ('Fraction(%r, %r)' % (self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000207
208 def __str__(self):
209 """str(self)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000210 if self._denominator == 1:
211 return str(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000212 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000213 return '%s/%s' % (self._numerator, self._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000214
215 def _operator_fallbacks(monomorphic_operator, fallback_operator):
216 """Generates forward and reverse operators given a purely-rational
217 operator and a function from the operator module.
218
219 Use this like:
220 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
221
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000222 In general, we want to implement the arithmetic operations so
223 that mixed-mode operations either call an implementation whose
224 author knew about the types of both arguments, or convert both
225 to the nearest built in type and do the operation there. In
Mark Dickinsond058cd22008-02-10 21:29:51 +0000226 Fraction, that means that we define __add__ and __radd__ as:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000227
228 def __add__(self, other):
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000229 # Both types have numerators/denominator attributes,
230 # so do the operation directly
Mark Dickinsond058cd22008-02-10 21:29:51 +0000231 if isinstance(other, (int, long, Fraction)):
232 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000233 other.numerator * self.denominator,
234 self.denominator * other.denominator)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000235 # float and complex don't have those operations, but we
236 # know about those types, so special case them.
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000237 elif isinstance(other, float):
238 return float(self) + other
239 elif isinstance(other, complex):
240 return complex(self) + other
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000241 # Let the other type take over.
242 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000243
244 def __radd__(self, other):
245 # radd handles more types than add because there's
246 # nothing left to fall back to.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000247 if isinstance(other, Rational):
248 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000249 other.numerator * self.denominator,
250 self.denominator * other.denominator)
251 elif isinstance(other, Real):
252 return float(other) + float(self)
253 elif isinstance(other, Complex):
254 return complex(other) + complex(self)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000255 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000256
257
258 There are 5 different cases for a mixed-type addition on
Mark Dickinsond058cd22008-02-10 21:29:51 +0000259 Fraction. I'll refer to all of the above code that doesn't
260 refer to Fraction, float, or complex as "boilerplate". 'r'
261 will be an instance of Fraction, which is a subtype of
262 Rational (r : Fraction <: Rational), and b : B <:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000263 Complex. The first three involve 'r + b':
264
Mark Dickinsond058cd22008-02-10 21:29:51 +0000265 1. If B <: Fraction, int, float, or complex, we handle
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000266 that specially, and all is well.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000267 2. If Fraction falls back to the boilerplate code, and it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000268 were to return a value from __add__, we'd miss the
269 possibility that B defines a more intelligent __radd__,
270 so the boilerplate should return NotImplemented from
Mark Dickinsond058cd22008-02-10 21:29:51 +0000271 __add__. In particular, we don't handle Rational
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000272 here, even though we could get an exact answer, in case
273 the other type wants to do something special.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000274 3. If B <: Fraction, Python tries B.__radd__ before
275 Fraction.__add__. This is ok, because it was
276 implemented with knowledge of Fraction, so it can
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000277 handle those instances before delegating to Real or
278 Complex.
279
280 The next two situations describe 'b + r'. We assume that b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000281 didn't know about Fraction in its implementation, and that it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000282 uses similar boilerplate code:
283
Mark Dickinsond058cd22008-02-10 21:29:51 +0000284 4. If B <: Rational, then __radd_ converts both to the
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000285 builtin rational type (hey look, that's us) and
286 proceeds.
287 5. Otherwise, __radd__ tries to find the nearest common
288 base ABC, and fall back to its builtin type. Since this
289 class doesn't subclass a concrete type, there's no
290 implementation to fall back to, so we need to try as
291 hard as possible to return an actual value, or the user
292 will get a TypeError.
293
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000294 """
295 def forward(a, b):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000296 if isinstance(b, (int, long, Fraction)):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000297 return monomorphic_operator(a, b)
298 elif isinstance(b, float):
299 return fallback_operator(float(a), b)
300 elif isinstance(b, complex):
301 return fallback_operator(complex(a), b)
302 else:
303 return NotImplemented
304 forward.__name__ = '__' + fallback_operator.__name__ + '__'
305 forward.__doc__ = monomorphic_operator.__doc__
306
307 def reverse(b, a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000308 if isinstance(a, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000309 # Includes ints.
310 return monomorphic_operator(a, b)
311 elif isinstance(a, numbers.Real):
312 return fallback_operator(float(a), float(b))
313 elif isinstance(a, numbers.Complex):
314 return fallback_operator(complex(a), complex(b))
315 else:
316 return NotImplemented
317 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
318 reverse.__doc__ = monomorphic_operator.__doc__
319
320 return forward, reverse
321
322 def _add(a, b):
323 """a + b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000324 return Fraction(a.numerator * b.denominator +
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000325 b.numerator * a.denominator,
326 a.denominator * b.denominator)
327
328 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
329
330 def _sub(a, b):
331 """a - b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000332 return Fraction(a.numerator * b.denominator -
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000333 b.numerator * a.denominator,
334 a.denominator * b.denominator)
335
336 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
337
338 def _mul(a, b):
339 """a * b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000340 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000341
342 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
343
344 def _div(a, b):
345 """a / b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000346 return Fraction(a.numerator * b.denominator,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000347 a.denominator * b.numerator)
348
349 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
350 __div__, __rdiv__ = _operator_fallbacks(_div, operator.div)
351
Raymond Hettinger909e3342008-01-24 23:50:26 +0000352 def __floordiv__(a, b):
353 """a // b"""
354 # Will be math.floor(a / b) in 3.0.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000355 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000356 if isinstance(div, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000357 # trunc(math.floor(div)) doesn't work if the rational is
358 # more precise than a float because the intermediate
359 # rounding may cross an integer boundary.
360 return div.numerator // div.denominator
361 else:
362 return math.floor(div)
363
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000364 def __rfloordiv__(b, a):
365 """a // b"""
366 # Will be math.floor(a / b) in 3.0.
Raymond Hettinger909e3342008-01-24 23:50:26 +0000367 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000368 if isinstance(div, Rational):
Raymond Hettinger909e3342008-01-24 23:50:26 +0000369 # trunc(math.floor(div)) doesn't work if the rational is
370 # more precise than a float because the intermediate
371 # rounding may cross an integer boundary.
372 return div.numerator // div.denominator
373 else:
374 return math.floor(div)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000375
376 def __mod__(a, b):
377 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000378 div = a // b
379 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000380
381 def __rmod__(b, a):
382 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000383 div = a // b
384 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000385
386 def __pow__(a, b):
387 """a ** b
388
389 If b is not an integer, the result will be a float or complex
390 since roots are generally irrational. If b is an integer, the
391 result will be rational.
392
393 """
Mark Dickinsond058cd22008-02-10 21:29:51 +0000394 if isinstance(b, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000395 if b.denominator == 1:
396 power = b.numerator
397 if power >= 0:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000398 return Fraction(a._numerator ** power,
399 a._denominator ** power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000400 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000401 return Fraction(a._denominator ** -power,
402 a._numerator ** -power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000403 else:
404 # A fractional power will generally produce an
405 # irrational number.
406 return float(a) ** float(b)
407 else:
408 return float(a) ** b
409
410 def __rpow__(b, a):
411 """a ** b"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000412 if b._denominator == 1 and b._numerator >= 0:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000413 # If a is an int, keep it that way if possible.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000414 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000415
Mark Dickinsond058cd22008-02-10 21:29:51 +0000416 if isinstance(a, Rational):
417 return Fraction(a.numerator, a.denominator) ** b
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000418
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000419 if b._denominator == 1:
420 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000421
422 return a ** float(b)
423
424 def __pos__(a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000425 """+a: Coerces a subclass instance to Fraction"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000426 return Fraction(a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000427
428 def __neg__(a):
429 """-a"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000430 return Fraction(-a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000431
432 def __abs__(a):
433 """abs(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000434 return Fraction(abs(a._numerator), a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000435
436 def __trunc__(a):
437 """trunc(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000438 if a._numerator < 0:
439 return -(-a._numerator // a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000440 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000441 return a._numerator // a._denominator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000442
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000443 def __hash__(self):
444 """hash(self)
445
446 Tricky because values that are exactly representable as a
447 float must have the same hash as that float.
448
449 """
Raymond Hettinger921cb5d2008-01-25 00:33:45 +0000450 # XXX since this method is expensive, consider caching the result
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000451 if self._denominator == 1:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000452 # Get integers right.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000453 return hash(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000454 # Expensive check, but definitely correct.
455 if self == float(self):
456 return hash(float(self))
457 else:
458 # Use tuple's hash to avoid a high collision rate on
459 # simple fractions.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000460 return hash((self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000461
462 def __eq__(a, b):
463 """a == b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000464 if isinstance(b, Rational):
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000465 return (a._numerator == b.numerator and
466 a._denominator == b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000467 if isinstance(b, numbers.Complex) and b.imag == 0:
468 b = b.real
469 if isinstance(b, float):
470 return a == a.from_float(b)
471 else:
472 # XXX: If b.__eq__ is implemented like this method, it may
473 # give the wrong answer after float(a) changes a's
474 # value. Better ways of doing this are welcome.
475 return float(a) == b
476
477 def _subtractAndCompareToZero(a, b, op):
478 """Helper function for comparison operators.
479
480 Subtracts b from a, exactly if possible, and compares the
481 result with 0 using op, in such a way that the comparison
482 won't recurse. If the difference raises a TypeError, returns
483 NotImplemented instead.
484
485 """
486 if isinstance(b, numbers.Complex) and b.imag == 0:
487 b = b.real
488 if isinstance(b, float):
489 b = a.from_float(b)
490 try:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000491 # XXX: If b <: Real but not <: Rational, this is likely
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000492 # to fall back to a float. If the actual values differ by
493 # less than MIN_FLOAT, this could falsely call them equal,
494 # which would make <= inconsistent with ==. Better ways of
495 # doing this are welcome.
496 diff = a - b
497 except TypeError:
498 return NotImplemented
Mark Dickinsond058cd22008-02-10 21:29:51 +0000499 if isinstance(diff, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000500 return op(diff.numerator, 0)
501 return op(diff, 0)
502
503 def __lt__(a, b):
504 """a < b"""
505 return a._subtractAndCompareToZero(b, operator.lt)
506
507 def __gt__(a, b):
508 """a > b"""
509 return a._subtractAndCompareToZero(b, operator.gt)
510
511 def __le__(a, b):
512 """a <= b"""
513 return a._subtractAndCompareToZero(b, operator.le)
514
515 def __ge__(a, b):
516 """a >= b"""
517 return a._subtractAndCompareToZero(b, operator.ge)
518
519 def __nonzero__(a):
520 """a != 0"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000521 return a._numerator != 0
Raymond Hettingera6216742008-01-25 00:21:54 +0000522
523 # support for pickling, copy, and deepcopy
524
525 def __reduce__(self):
526 return (self.__class__, (str(self),))
527
528 def __copy__(self):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000529 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000530 return self # I'm immutable; therefore I am my own clone
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000531 return self.__class__(self._numerator, self._denominator)
Raymond Hettingera6216742008-01-25 00:21:54 +0000532
533 def __deepcopy__(self, memo):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000534 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000535 return self # My components are also immutable
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000536 return self.__class__(self._numerator, self._denominator)