blob: 6bde7746b8ecbf7a8a70fbfd8bbb86346fcfeb7f [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 """
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000113 if not isinstance(f, float):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000114 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
115 (cls.__name__, f, type(f).__name__))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000116 if math.isnan(f) or math.isinf(f):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000117 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
118 return cls(*f.as_integer_ratio())
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000119
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000120 @classmethod
121 def from_decimal(cls, dec):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000122 """Converts a finite Decimal instance to a rational number, exactly."""
123 from decimal import Decimal
124 if not isinstance(dec, Decimal):
125 raise TypeError(
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000126 "%s.from_decimal() only takes Decimals, not %r (%s)" %
127 (cls.__name__, dec, type(dec).__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000128 if not dec.is_finite():
129 # Catches infinities and nans.
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000130 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000131 sign, digits, exp = dec.as_tuple()
132 digits = int(''.join(map(str, digits)))
133 if sign:
134 digits = -digits
135 if exp >= 0:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000136 return cls(digits * 10 ** exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000137 else:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000138 return cls(digits, 10 ** -exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000139
Mark Dickinsone1b82472008-02-12 21:31:59 +0000140 def limit_denominator(self, max_denominator=1000000):
141 """Closest Fraction to self with denominator at most max_denominator.
Raymond Hettingercf109262008-01-24 00:54:21 +0000142
Mark Dickinsone1b82472008-02-12 21:31:59 +0000143 >>> Fraction('3.141592653589793').limit_denominator(10)
144 Fraction(22, 7)
145 >>> Fraction('3.141592653589793').limit_denominator(100)
146 Fraction(311, 99)
147 >>> Fraction(1234, 5678).limit_denominator(10000)
148 Fraction(1234, 5678)
Raymond Hettingercf109262008-01-24 00:54:21 +0000149
Mark Dickinsone1b82472008-02-12 21:31:59 +0000150 """
151 # Algorithm notes: For any real number x, define a *best upper
152 # approximation* to x to be a rational number p/q such that:
153 #
154 # (1) p/q >= x, and
155 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
156 #
157 # Define *best lower approximation* similarly. Then it can be
158 # proved that a rational number is a best upper or lower
159 # approximation to x if, and only if, it is a convergent or
160 # semiconvergent of the (unique shortest) continued fraction
161 # associated to x.
162 #
163 # To find a best rational approximation with denominator <= M,
164 # we find the best upper and lower approximations with
165 # denominator <= M and take whichever of these is closer to x.
166 # In the event of a tie, the bound with smaller denominator is
167 # chosen. If both denominators are equal (which can happen
168 # only when max_denominator == 1 and self is midway between
169 # two integers) the lower bound---i.e., the floor of self, is
170 # taken.
171
172 if max_denominator < 1:
173 raise ValueError("max_denominator should be at least 1")
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000174 if self._denominator <= max_denominator:
Mark Dickinsone1b82472008-02-12 21:31:59 +0000175 return Fraction(self)
176
177 p0, q0, p1, q1 = 0, 1, 1, 0
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000178 n, d = self._numerator, self._denominator
Mark Dickinsone1b82472008-02-12 21:31:59 +0000179 while True:
180 a = n//d
181 q2 = q0+a*q1
182 if q2 > max_denominator:
Raymond Hettingercf109262008-01-24 00:54:21 +0000183 break
Mark Dickinsone1b82472008-02-12 21:31:59 +0000184 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
185 n, d = d, n-a*d
186
187 k = (max_denominator-q0)//q1
188 bound1 = Fraction(p0+k*p1, q0+k*q1)
189 bound2 = Fraction(p1, q1)
190 if abs(bound2 - self) <= abs(bound1-self):
191 return bound2
192 else:
193 return bound1
Raymond Hettingercf109262008-01-24 00:54:21 +0000194
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +0000195 @property
196 def numerator(a):
197 return a._numerator
198
199 @property
200 def denominator(a):
201 return a._denominator
202
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000203 def __repr__(self):
204 """repr(self)"""
Mark Dickinson3af386a2008-06-27 10:11:52 +0000205 return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000206
207 def __str__(self):
208 """str(self)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000209 if self._denominator == 1:
210 return str(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000211 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000212 return '%s/%s' % (self._numerator, self._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000213
214 def _operator_fallbacks(monomorphic_operator, fallback_operator):
215 """Generates forward and reverse operators given a purely-rational
216 operator and a function from the operator module.
217
218 Use this like:
219 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
220
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000221 In general, we want to implement the arithmetic operations so
222 that mixed-mode operations either call an implementation whose
223 author knew about the types of both arguments, or convert both
224 to the nearest built in type and do the operation there. In
Mark Dickinsond058cd22008-02-10 21:29:51 +0000225 Fraction, that means that we define __add__ and __radd__ as:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000226
227 def __add__(self, other):
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000228 # Both types have numerators/denominator attributes,
229 # so do the operation directly
Mark Dickinsond058cd22008-02-10 21:29:51 +0000230 if isinstance(other, (int, long, Fraction)):
231 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000232 other.numerator * self.denominator,
233 self.denominator * other.denominator)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000234 # float and complex don't have those operations, but we
235 # know about those types, so special case them.
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000236 elif isinstance(other, float):
237 return float(self) + other
238 elif isinstance(other, complex):
239 return complex(self) + other
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000240 # Let the other type take over.
241 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000242
243 def __radd__(self, other):
244 # radd handles more types than add because there's
245 # nothing left to fall back to.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000246 if isinstance(other, Rational):
247 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000248 other.numerator * self.denominator,
249 self.denominator * other.denominator)
250 elif isinstance(other, Real):
251 return float(other) + float(self)
252 elif isinstance(other, Complex):
253 return complex(other) + complex(self)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000254 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000255
256
257 There are 5 different cases for a mixed-type addition on
Mark Dickinsond058cd22008-02-10 21:29:51 +0000258 Fraction. I'll refer to all of the above code that doesn't
259 refer to Fraction, float, or complex as "boilerplate". 'r'
260 will be an instance of Fraction, which is a subtype of
261 Rational (r : Fraction <: Rational), and b : B <:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000262 Complex. The first three involve 'r + b':
263
Mark Dickinsond058cd22008-02-10 21:29:51 +0000264 1. If B <: Fraction, int, float, or complex, we handle
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000265 that specially, and all is well.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000266 2. If Fraction falls back to the boilerplate code, and it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000267 were to return a value from __add__, we'd miss the
268 possibility that B defines a more intelligent __radd__,
269 so the boilerplate should return NotImplemented from
Mark Dickinsond058cd22008-02-10 21:29:51 +0000270 __add__. In particular, we don't handle Rational
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000271 here, even though we could get an exact answer, in case
272 the other type wants to do something special.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000273 3. If B <: Fraction, Python tries B.__radd__ before
274 Fraction.__add__. This is ok, because it was
275 implemented with knowledge of Fraction, so it can
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000276 handle those instances before delegating to Real or
277 Complex.
278
279 The next two situations describe 'b + r'. We assume that b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000280 didn't know about Fraction in its implementation, and that it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000281 uses similar boilerplate code:
282
Mark Dickinsond058cd22008-02-10 21:29:51 +0000283 4. If B <: Rational, then __radd_ converts both to the
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000284 builtin rational type (hey look, that's us) and
285 proceeds.
286 5. Otherwise, __radd__ tries to find the nearest common
287 base ABC, and fall back to its builtin type. Since this
288 class doesn't subclass a concrete type, there's no
289 implementation to fall back to, so we need to try as
290 hard as possible to return an actual value, or the user
291 will get a TypeError.
292
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000293 """
294 def forward(a, b):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000295 if isinstance(b, (int, long, Fraction)):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000296 return monomorphic_operator(a, b)
297 elif isinstance(b, float):
298 return fallback_operator(float(a), b)
299 elif isinstance(b, complex):
300 return fallback_operator(complex(a), b)
301 else:
302 return NotImplemented
303 forward.__name__ = '__' + fallback_operator.__name__ + '__'
304 forward.__doc__ = monomorphic_operator.__doc__
305
306 def reverse(b, a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000307 if isinstance(a, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000308 # Includes ints.
309 return monomorphic_operator(a, b)
310 elif isinstance(a, numbers.Real):
311 return fallback_operator(float(a), float(b))
312 elif isinstance(a, numbers.Complex):
313 return fallback_operator(complex(a), complex(b))
314 else:
315 return NotImplemented
316 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
317 reverse.__doc__ = monomorphic_operator.__doc__
318
319 return forward, reverse
320
321 def _add(a, b):
322 """a + b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000323 return Fraction(a.numerator * b.denominator +
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000324 b.numerator * a.denominator,
325 a.denominator * b.denominator)
326
327 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
328
329 def _sub(a, b):
330 """a - b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000331 return Fraction(a.numerator * b.denominator -
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000332 b.numerator * a.denominator,
333 a.denominator * b.denominator)
334
335 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
336
337 def _mul(a, b):
338 """a * b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000339 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000340
341 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
342
343 def _div(a, b):
344 """a / b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000345 return Fraction(a.numerator * b.denominator,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000346 a.denominator * b.numerator)
347
348 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
349 __div__, __rdiv__ = _operator_fallbacks(_div, operator.div)
350
Raymond Hettinger909e3342008-01-24 23:50:26 +0000351 def __floordiv__(a, b):
352 """a // b"""
353 # Will be math.floor(a / b) in 3.0.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000354 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000355 if isinstance(div, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000356 # trunc(math.floor(div)) doesn't work if the rational is
357 # more precise than a float because the intermediate
358 # rounding may cross an integer boundary.
359 return div.numerator // div.denominator
360 else:
361 return math.floor(div)
362
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000363 def __rfloordiv__(b, a):
364 """a // b"""
365 # Will be math.floor(a / b) in 3.0.
Raymond Hettinger909e3342008-01-24 23:50:26 +0000366 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000367 if isinstance(div, Rational):
Raymond Hettinger909e3342008-01-24 23:50:26 +0000368 # trunc(math.floor(div)) doesn't work if the rational is
369 # more precise than a float because the intermediate
370 # rounding may cross an integer boundary.
371 return div.numerator // div.denominator
372 else:
373 return math.floor(div)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000374
375 def __mod__(a, b):
376 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000377 div = a // b
378 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000379
380 def __rmod__(b, a):
381 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000382 div = a // b
383 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000384
385 def __pow__(a, b):
386 """a ** b
387
388 If b is not an integer, the result will be a float or complex
389 since roots are generally irrational. If b is an integer, the
390 result will be rational.
391
392 """
Mark Dickinsond058cd22008-02-10 21:29:51 +0000393 if isinstance(b, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000394 if b.denominator == 1:
395 power = b.numerator
396 if power >= 0:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000397 return Fraction(a._numerator ** power,
398 a._denominator ** power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000399 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000400 return Fraction(a._denominator ** -power,
401 a._numerator ** -power)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000402 else:
403 # A fractional power will generally produce an
404 # irrational number.
405 return float(a) ** float(b)
406 else:
407 return float(a) ** b
408
409 def __rpow__(b, a):
410 """a ** b"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000411 if b._denominator == 1 and b._numerator >= 0:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000412 # If a is an int, keep it that way if possible.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000413 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000414
Mark Dickinsond058cd22008-02-10 21:29:51 +0000415 if isinstance(a, Rational):
416 return Fraction(a.numerator, a.denominator) ** b
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000417
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000418 if b._denominator == 1:
419 return a ** b._numerator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000420
421 return a ** float(b)
422
423 def __pos__(a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000424 """+a: Coerces a subclass instance to Fraction"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000425 return Fraction(a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000426
427 def __neg__(a):
428 """-a"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000429 return Fraction(-a._numerator, a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000430
431 def __abs__(a):
432 """abs(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000433 return Fraction(abs(a._numerator), a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000434
435 def __trunc__(a):
436 """trunc(a)"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000437 if a._numerator < 0:
438 return -(-a._numerator // a._denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000439 else:
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000440 return a._numerator // a._denominator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000441
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000442 def __hash__(self):
443 """hash(self)
444
445 Tricky because values that are exactly representable as a
446 float must have the same hash as that float.
447
448 """
Raymond Hettinger921cb5d2008-01-25 00:33:45 +0000449 # XXX since this method is expensive, consider caching the result
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000450 if self._denominator == 1:
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000451 # Get integers right.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000452 return hash(self._numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000453 # Expensive check, but definitely correct.
454 if self == float(self):
455 return hash(float(self))
456 else:
457 # Use tuple's hash to avoid a high collision rate on
458 # simple fractions.
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000459 return hash((self._numerator, self._denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000460
461 def __eq__(a, b):
462 """a == b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000463 if isinstance(b, Rational):
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000464 return (a._numerator == b.numerator and
465 a._denominator == b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000466 if isinstance(b, numbers.Complex) and b.imag == 0:
467 b = b.real
468 if isinstance(b, float):
469 return a == a.from_float(b)
470 else:
471 # XXX: If b.__eq__ is implemented like this method, it may
472 # give the wrong answer after float(a) changes a's
473 # value. Better ways of doing this are welcome.
474 return float(a) == b
475
476 def _subtractAndCompareToZero(a, b, op):
477 """Helper function for comparison operators.
478
479 Subtracts b from a, exactly if possible, and compares the
480 result with 0 using op, in such a way that the comparison
481 won't recurse. If the difference raises a TypeError, returns
482 NotImplemented instead.
483
484 """
485 if isinstance(b, numbers.Complex) and b.imag == 0:
486 b = b.real
487 if isinstance(b, float):
488 b = a.from_float(b)
489 try:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000490 # XXX: If b <: Real but not <: Rational, this is likely
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000491 # to fall back to a float. If the actual values differ by
492 # less than MIN_FLOAT, this could falsely call them equal,
493 # which would make <= inconsistent with ==. Better ways of
494 # doing this are welcome.
495 diff = a - b
496 except TypeError:
497 return NotImplemented
Mark Dickinsond058cd22008-02-10 21:29:51 +0000498 if isinstance(diff, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000499 return op(diff.numerator, 0)
500 return op(diff, 0)
501
502 def __lt__(a, b):
503 """a < b"""
504 return a._subtractAndCompareToZero(b, operator.lt)
505
506 def __gt__(a, b):
507 """a > b"""
508 return a._subtractAndCompareToZero(b, operator.gt)
509
510 def __le__(a, b):
511 """a <= b"""
512 return a._subtractAndCompareToZero(b, operator.le)
513
514 def __ge__(a, b):
515 """a >= b"""
516 return a._subtractAndCompareToZero(b, operator.ge)
517
518 def __nonzero__(a):
519 """a != 0"""
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000520 return a._numerator != 0
Raymond Hettingera6216742008-01-25 00:21:54 +0000521
522 # support for pickling, copy, and deepcopy
523
524 def __reduce__(self):
525 return (self.__class__, (str(self),))
526
527 def __copy__(self):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000528 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000529 return self # I'm immutable; therefore I am my own clone
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000530 return self.__class__(self._numerator, self._denominator)
Raymond Hettingera6216742008-01-25 00:21:54 +0000531
532 def __deepcopy__(self, memo):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000533 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000534 return self # My components are also immutable
Jeffrey Yasskin339f5e32008-02-14 07:49:25 +0000535 return self.__class__(self._numerator, self._denominator)