blob: 53ff78549c4e5aab28ebce7ffd69d2014803d457 [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
Mark Dickinsond058cd22008-02-10 21:29:51 +000012__all__ = ["Fraction"]
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
67 if denominator == 1:
68 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
89 elif (not isinstance(numerator, numbers.Integral) and
Mark Dickinsond058cd22008-02-10 21:29:51 +000090 isinstance(numerator, Rational)):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +000091 # Handle copies from other rationals.
92 other_rational = numerator
93 numerator = other_rational.numerator
94 denominator = other_rational.denominator
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000095
96 if (not isinstance(numerator, numbers.Integral) or
97 not isinstance(denominator, numbers.Integral)):
Mark Dickinsond058cd22008-02-10 21:29:51 +000098 raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
Jeffrey Yasskind7b00332008-01-15 07:46:24 +000099 " Both arguments must be integral." % locals())
100
101 if denominator == 0:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000102 raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000103
Jeffrey Yasskin3e1a3732008-01-27 05:40:35 +0000104 g = gcd(numerator, denominator)
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +0000105 self._numerator = int(numerator // g)
106 self._denominator = int(denominator // g)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000107 return self
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000108
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000109 @classmethod
110 def from_float(cls, f):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000111 """Converts a finite float to a rational number, exactly.
112
Mark Dickinsond058cd22008-02-10 21:29:51 +0000113 Beware that Fraction.from_float(0.3) != Fraction(3, 10).
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000114
115 """
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000116 if not isinstance(f, float):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000117 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
118 (cls.__name__, f, type(f).__name__))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000119 if math.isnan(f) or math.isinf(f):
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000120 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
121 return cls(*f.as_integer_ratio())
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000122
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000123 @classmethod
124 def from_decimal(cls, dec):
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000125 """Converts a finite Decimal instance to a rational number, exactly."""
126 from decimal import Decimal
127 if not isinstance(dec, Decimal):
128 raise TypeError(
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000129 "%s.from_decimal() only takes Decimals, not %r (%s)" %
130 (cls.__name__, dec, type(dec).__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000131 if not dec.is_finite():
132 # Catches infinities and nans.
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000133 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000134 sign, digits, exp = dec.as_tuple()
135 digits = int(''.join(map(str, digits)))
136 if sign:
137 digits = -digits
138 if exp >= 0:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000139 return cls(digits * 10 ** exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000140 else:
Mark Dickinson0aa52a12008-02-12 21:40:53 +0000141 return cls(digits, 10 ** -exp)
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000142
Mark Dickinsone1b82472008-02-12 21:31:59 +0000143 def limit_denominator(self, max_denominator=1000000):
144 """Closest Fraction to self with denominator at most max_denominator.
Raymond Hettingercf109262008-01-24 00:54:21 +0000145
Mark Dickinsone1b82472008-02-12 21:31:59 +0000146 >>> Fraction('3.141592653589793').limit_denominator(10)
147 Fraction(22, 7)
148 >>> Fraction('3.141592653589793').limit_denominator(100)
149 Fraction(311, 99)
150 >>> Fraction(1234, 5678).limit_denominator(10000)
151 Fraction(1234, 5678)
Raymond Hettingercf109262008-01-24 00:54:21 +0000152
Mark Dickinsone1b82472008-02-12 21:31:59 +0000153 """
154 # Algorithm notes: For any real number x, define a *best upper
155 # approximation* to x to be a rational number p/q such that:
156 #
157 # (1) p/q >= x, and
158 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
159 #
160 # Define *best lower approximation* similarly. Then it can be
161 # proved that a rational number is a best upper or lower
162 # approximation to x if, and only if, it is a convergent or
163 # semiconvergent of the (unique shortest) continued fraction
164 # associated to x.
165 #
166 # To find a best rational approximation with denominator <= M,
167 # we find the best upper and lower approximations with
168 # denominator <= M and take whichever of these is closer to x.
169 # In the event of a tie, the bound with smaller denominator is
170 # chosen. If both denominators are equal (which can happen
171 # only when max_denominator == 1 and self is midway between
172 # two integers) the lower bound---i.e., the floor of self, is
173 # taken.
174
175 if max_denominator < 1:
176 raise ValueError("max_denominator should be at least 1")
Raymond Hettinger9c6d81f2008-01-25 01:23:38 +0000177 if self.denominator <= max_denominator:
Mark Dickinsone1b82472008-02-12 21:31:59 +0000178 return Fraction(self)
179
180 p0, q0, p1, q1 = 0, 1, 1, 0
181 n, d = self.numerator, self.denominator
182 while True:
183 a = n//d
184 q2 = q0+a*q1
185 if q2 > max_denominator:
Raymond Hettingercf109262008-01-24 00:54:21 +0000186 break
Mark Dickinsone1b82472008-02-12 21:31:59 +0000187 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
188 n, d = d, n-a*d
189
190 k = (max_denominator-q0)//q1
191 bound1 = Fraction(p0+k*p1, q0+k*q1)
192 bound2 = Fraction(p1, q1)
193 if abs(bound2 - self) <= abs(bound1-self):
194 return bound2
195 else:
196 return bound1
Raymond Hettingercf109262008-01-24 00:54:21 +0000197
Jeffrey Yasskindc2964b2008-02-01 07:05:46 +0000198 @property
199 def numerator(a):
200 return a._numerator
201
202 @property
203 def denominator(a):
204 return a._denominator
205
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000206 def __repr__(self):
207 """repr(self)"""
Mark Dickinsoncd873fc2008-02-11 03:11:55 +0000208 return ('Fraction(%r, %r)' % (self.numerator, self.denominator))
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000209
210 def __str__(self):
211 """str(self)"""
212 if self.denominator == 1:
213 return str(self.numerator)
214 else:
Jeffrey Yasskin45169fb2008-01-19 09:56:06 +0000215 return '%s/%s' % (self.numerator, self.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000216
217 def _operator_fallbacks(monomorphic_operator, fallback_operator):
218 """Generates forward and reverse operators given a purely-rational
219 operator and a function from the operator module.
220
221 Use this like:
222 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
223
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000224 In general, we want to implement the arithmetic operations so
225 that mixed-mode operations either call an implementation whose
226 author knew about the types of both arguments, or convert both
227 to the nearest built in type and do the operation there. In
Mark Dickinsond058cd22008-02-10 21:29:51 +0000228 Fraction, that means that we define __add__ and __radd__ as:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000229
230 def __add__(self, other):
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000231 # Both types have numerators/denominator attributes,
232 # so do the operation directly
Mark Dickinsond058cd22008-02-10 21:29:51 +0000233 if isinstance(other, (int, long, Fraction)):
234 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000235 other.numerator * self.denominator,
236 self.denominator * other.denominator)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000237 # float and complex don't have those operations, but we
238 # know about those types, so special case them.
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000239 elif isinstance(other, float):
240 return float(self) + other
241 elif isinstance(other, complex):
242 return complex(self) + other
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000243 # Let the other type take over.
244 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000245
246 def __radd__(self, other):
247 # radd handles more types than add because there's
248 # nothing left to fall back to.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000249 if isinstance(other, Rational):
250 return Fraction(self.numerator * other.denominator +
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000251 other.numerator * self.denominator,
252 self.denominator * other.denominator)
253 elif isinstance(other, Real):
254 return float(other) + float(self)
255 elif isinstance(other, Complex):
256 return complex(other) + complex(self)
Raymond Hettinger2df20a32008-01-31 22:07:16 +0000257 return NotImplemented
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000258
259
260 There are 5 different cases for a mixed-type addition on
Mark Dickinsond058cd22008-02-10 21:29:51 +0000261 Fraction. I'll refer to all of the above code that doesn't
262 refer to Fraction, float, or complex as "boilerplate". 'r'
263 will be an instance of Fraction, which is a subtype of
264 Rational (r : Fraction <: Rational), and b : B <:
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000265 Complex. The first three involve 'r + b':
266
Mark Dickinsond058cd22008-02-10 21:29:51 +0000267 1. If B <: Fraction, int, float, or complex, we handle
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000268 that specially, and all is well.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000269 2. If Fraction falls back to the boilerplate code, and it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000270 were to return a value from __add__, we'd miss the
271 possibility that B defines a more intelligent __radd__,
272 so the boilerplate should return NotImplemented from
Mark Dickinsond058cd22008-02-10 21:29:51 +0000273 __add__. In particular, we don't handle Rational
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000274 here, even though we could get an exact answer, in case
275 the other type wants to do something special.
Mark Dickinsond058cd22008-02-10 21:29:51 +0000276 3. If B <: Fraction, Python tries B.__radd__ before
277 Fraction.__add__. This is ok, because it was
278 implemented with knowledge of Fraction, so it can
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000279 handle those instances before delegating to Real or
280 Complex.
281
282 The next two situations describe 'b + r'. We assume that b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000283 didn't know about Fraction in its implementation, and that it
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000284 uses similar boilerplate code:
285
Mark Dickinsond058cd22008-02-10 21:29:51 +0000286 4. If B <: Rational, then __radd_ converts both to the
Jeffrey Yasskinb23dea62008-01-31 07:44:11 +0000287 builtin rational type (hey look, that's us) and
288 proceeds.
289 5. Otherwise, __radd__ tries to find the nearest common
290 base ABC, and fall back to its builtin type. Since this
291 class doesn't subclass a concrete type, there's no
292 implementation to fall back to, so we need to try as
293 hard as possible to return an actual value, or the user
294 will get a TypeError.
295
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000296 """
297 def forward(a, b):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000298 if isinstance(b, (int, long, Fraction)):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000299 return monomorphic_operator(a, b)
300 elif isinstance(b, float):
301 return fallback_operator(float(a), b)
302 elif isinstance(b, complex):
303 return fallback_operator(complex(a), b)
304 else:
305 return NotImplemented
306 forward.__name__ = '__' + fallback_operator.__name__ + '__'
307 forward.__doc__ = monomorphic_operator.__doc__
308
309 def reverse(b, a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000310 if isinstance(a, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000311 # Includes ints.
312 return monomorphic_operator(a, b)
313 elif isinstance(a, numbers.Real):
314 return fallback_operator(float(a), float(b))
315 elif isinstance(a, numbers.Complex):
316 return fallback_operator(complex(a), complex(b))
317 else:
318 return NotImplemented
319 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
320 reverse.__doc__ = monomorphic_operator.__doc__
321
322 return forward, reverse
323
324 def _add(a, b):
325 """a + b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000326 return Fraction(a.numerator * b.denominator +
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000327 b.numerator * a.denominator,
328 a.denominator * b.denominator)
329
330 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
331
332 def _sub(a, b):
333 """a - b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000334 return Fraction(a.numerator * b.denominator -
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000335 b.numerator * a.denominator,
336 a.denominator * b.denominator)
337
338 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
339
340 def _mul(a, b):
341 """a * b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000342 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000343
344 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
345
346 def _div(a, b):
347 """a / b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000348 return Fraction(a.numerator * b.denominator,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000349 a.denominator * b.numerator)
350
351 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
352 __div__, __rdiv__ = _operator_fallbacks(_div, operator.div)
353
Raymond Hettinger909e3342008-01-24 23:50:26 +0000354 def __floordiv__(a, b):
355 """a // b"""
356 # Will be math.floor(a / b) in 3.0.
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000357 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000358 if isinstance(div, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000359 # trunc(math.floor(div)) doesn't work if the rational is
360 # more precise than a float because the intermediate
361 # rounding may cross an integer boundary.
362 return div.numerator // div.denominator
363 else:
364 return math.floor(div)
365
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000366 def __rfloordiv__(b, a):
367 """a // b"""
368 # Will be math.floor(a / b) in 3.0.
Raymond Hettinger909e3342008-01-24 23:50:26 +0000369 div = a / b
Mark Dickinsond058cd22008-02-10 21:29:51 +0000370 if isinstance(div, Rational):
Raymond Hettinger909e3342008-01-24 23:50:26 +0000371 # trunc(math.floor(div)) doesn't work if the rational is
372 # more precise than a float because the intermediate
373 # rounding may cross an integer boundary.
374 return div.numerator // div.denominator
375 else:
376 return math.floor(div)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000377
378 def __mod__(a, b):
379 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000380 div = a // b
381 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000382
383 def __rmod__(b, a):
384 """a % b"""
Raymond Hettinger909e3342008-01-24 23:50:26 +0000385 div = a // b
386 return a - b * div
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000387
388 def __pow__(a, b):
389 """a ** b
390
391 If b is not an integer, the result will be a float or complex
392 since roots are generally irrational. If b is an integer, the
393 result will be rational.
394
395 """
Mark Dickinsond058cd22008-02-10 21:29:51 +0000396 if isinstance(b, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000397 if b.denominator == 1:
398 power = b.numerator
399 if power >= 0:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000400 return Fraction(a.numerator ** power,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000401 a.denominator ** power)
402 else:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000403 return Fraction(a.denominator ** -power,
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000404 a.numerator ** -power)
405 else:
406 # A fractional power will generally produce an
407 # irrational number.
408 return float(a) ** float(b)
409 else:
410 return float(a) ** b
411
412 def __rpow__(b, a):
413 """a ** b"""
414 if b.denominator == 1 and b.numerator >= 0:
415 # If a is an int, keep it that way if possible.
416 return a ** b.numerator
417
Mark Dickinsond058cd22008-02-10 21:29:51 +0000418 if isinstance(a, Rational):
419 return Fraction(a.numerator, a.denominator) ** b
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000420
421 if b.denominator == 1:
422 return a ** b.numerator
423
424 return a ** float(b)
425
426 def __pos__(a):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000427 """+a: Coerces a subclass instance to Fraction"""
428 return Fraction(a.numerator, a.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000429
430 def __neg__(a):
431 """-a"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000432 return Fraction(-a.numerator, a.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000433
434 def __abs__(a):
435 """abs(a)"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000436 return Fraction(abs(a.numerator), a.denominator)
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000437
438 def __trunc__(a):
439 """trunc(a)"""
440 if a.numerator < 0:
441 return -(-a.numerator // a.denominator)
442 else:
443 return a.numerator // a.denominator
444
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000445 def __hash__(self):
446 """hash(self)
447
448 Tricky because values that are exactly representable as a
449 float must have the same hash as that float.
450
451 """
Raymond Hettinger921cb5d2008-01-25 00:33:45 +0000452 # XXX since this method is expensive, consider caching the result
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000453 if self.denominator == 1:
454 # Get integers right.
455 return hash(self.numerator)
456 # Expensive check, but definitely correct.
457 if self == float(self):
458 return hash(float(self))
459 else:
460 # Use tuple's hash to avoid a high collision rate on
461 # simple fractions.
462 return hash((self.numerator, self.denominator))
463
464 def __eq__(a, b):
465 """a == b"""
Mark Dickinsond058cd22008-02-10 21:29:51 +0000466 if isinstance(b, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000467 return (a.numerator == b.numerator and
468 a.denominator == b.denominator)
469 if isinstance(b, numbers.Complex) and b.imag == 0:
470 b = b.real
471 if isinstance(b, float):
472 return a == a.from_float(b)
473 else:
474 # XXX: If b.__eq__ is implemented like this method, it may
475 # give the wrong answer after float(a) changes a's
476 # value. Better ways of doing this are welcome.
477 return float(a) == b
478
479 def _subtractAndCompareToZero(a, b, op):
480 """Helper function for comparison operators.
481
482 Subtracts b from a, exactly if possible, and compares the
483 result with 0 using op, in such a way that the comparison
484 won't recurse. If the difference raises a TypeError, returns
485 NotImplemented instead.
486
487 """
488 if isinstance(b, numbers.Complex) and b.imag == 0:
489 b = b.real
490 if isinstance(b, float):
491 b = a.from_float(b)
492 try:
Mark Dickinsond058cd22008-02-10 21:29:51 +0000493 # XXX: If b <: Real but not <: Rational, this is likely
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000494 # to fall back to a float. If the actual values differ by
495 # less than MIN_FLOAT, this could falsely call them equal,
496 # which would make <= inconsistent with ==. Better ways of
497 # doing this are welcome.
498 diff = a - b
499 except TypeError:
500 return NotImplemented
Mark Dickinsond058cd22008-02-10 21:29:51 +0000501 if isinstance(diff, Rational):
Jeffrey Yasskind7b00332008-01-15 07:46:24 +0000502 return op(diff.numerator, 0)
503 return op(diff, 0)
504
505 def __lt__(a, b):
506 """a < b"""
507 return a._subtractAndCompareToZero(b, operator.lt)
508
509 def __gt__(a, b):
510 """a > b"""
511 return a._subtractAndCompareToZero(b, operator.gt)
512
513 def __le__(a, b):
514 """a <= b"""
515 return a._subtractAndCompareToZero(b, operator.le)
516
517 def __ge__(a, b):
518 """a >= b"""
519 return a._subtractAndCompareToZero(b, operator.ge)
520
521 def __nonzero__(a):
522 """a != 0"""
523 return a.numerator != 0
Raymond Hettingera6216742008-01-25 00:21:54 +0000524
525 # support for pickling, copy, and deepcopy
526
527 def __reduce__(self):
528 return (self.__class__, (str(self),))
529
530 def __copy__(self):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000531 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000532 return self # I'm immutable; therefore I am my own clone
533 return self.__class__(self.numerator, self.denominator)
534
535 def __deepcopy__(self, memo):
Mark Dickinsond058cd22008-02-10 21:29:51 +0000536 if type(self) == Fraction:
Raymond Hettingera6216742008-01-25 00:21:54 +0000537 return self # My components are also immutable
538 return self.__class__(self.numerator, self.denominator)