blob: 5242f8f88ca7fd3d255aa5e324669db9e0704658 [file] [log] [blame]
Guido van Rossum7736b5b2008-01-15 21:44:53 +00001# Originally contributed by Sjoerd Mullender.
2# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
3
Christian Heimes3feef612008-02-11 06:19:17 +00004"""Fraction, infinite-precision, real numbers."""
Guido van Rossum7736b5b2008-01-15 21:44:53 +00005
Guido van Rossum7736b5b2008-01-15 21:44:53 +00006import math
7import numbers
8import operator
Christian Heimes587c2bf2008-01-19 16:21:02 +00009import re
Guido van Rossum7736b5b2008-01-15 21:44:53 +000010
Raymond Hettingere580f5c2008-05-08 16:03:04 +000011__all__ = ['Fraction', 'gcd']
Guido van Rossum7736b5b2008-01-15 21:44:53 +000012
Guido van Rossum7736b5b2008-01-15 21:44:53 +000013
14
Christian Heimesaf98da12008-01-27 15:18:18 +000015def gcd(a, b):
16 """Calculate the Greatest Common Divisor of a and b.
Guido van Rossum7736b5b2008-01-15 21:44:53 +000017
18 Unless b==0, the result will have the same sign as b (so that when
19 b is divided by it, the result comes out positive).
20 """
21 while b:
22 a, b = b, a%b
23 return a
24
25
Christian Heimes292d3512008-02-03 16:51:08 +000026_RATIONAL_FORMAT = re.compile(r"""
27 \A\s* # optional whitespace at the start, then
28 (?P<sign>[-+]?) # an optional sign, then
29 (?=\d|\.\d) # lookahead for digit or .digit
30 (?P<num>\d*) # numerator (possibly empty)
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000031 (?: # followed by
32 (?:/(?P<denom>\d+))? # an optional denominator
Christian Heimes292d3512008-02-03 16:51:08 +000033 | # or
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000034 (?:\.(?P<decimal>\d*))? # an optional fractional part
35 (?:E(?P<exp>[-+]?\d+))? # and optional exponent
36 )
Christian Heimes292d3512008-02-03 16:51:08 +000037 \s*\Z # and optional whitespace to finish
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000038""", re.VERBOSE | re.IGNORECASE)
Christian Heimes587c2bf2008-01-19 16:21:02 +000039
40
Christian Heimes3feef612008-02-11 06:19:17 +000041class Fraction(numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +000042 """This class implements rational numbers.
43
Christian Heimes3feef612008-02-11 06:19:17 +000044 Fraction(8, 6) will produce a rational number equivalent to
Guido van Rossum7736b5b2008-01-15 21:44:53 +000045 4/3. Both arguments must be Integral. The numerator defaults to 0
Christian Heimes3feef612008-02-11 06:19:17 +000046 and the denominator defaults to 1 so that Fraction(3) == 3 and
47 Fraction() == 0.
Guido van Rossum7736b5b2008-01-15 21:44:53 +000048
Christian Heimes3feef612008-02-11 06:19:17 +000049 Fraction can also be constructed from strings of the form
Christian Heimesaf98da12008-01-27 15:18:18 +000050 '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
Christian Heimes587c2bf2008-01-19 16:21:02 +000051
Guido van Rossum7736b5b2008-01-15 21:44:53 +000052 """
53
Christian Heimes400adb02008-02-01 08:12:03 +000054 __slots__ = ('_numerator', '_denominator')
Guido van Rossum7736b5b2008-01-15 21:44:53 +000055
Christian Heimes587c2bf2008-01-19 16:21:02 +000056 # We're immutable, so use __new__ not __init__
57 def __new__(cls, numerator=0, denominator=1):
58 """Constructs a Rational.
59
Christian Heimesaf98da12008-01-27 15:18:18 +000060 Takes a string like '3/2' or '1.5', another Rational, or a
61 numerator/denominator pair.
Christian Heimes587c2bf2008-01-19 16:21:02 +000062
63 """
Christian Heimes3feef612008-02-11 06:19:17 +000064 self = super(Fraction, cls).__new__(cls)
Christian Heimes587c2bf2008-01-19 16:21:02 +000065
Christian Heimes68f5fbe2008-02-14 08:27:37 +000066 if not isinstance(numerator, int) and denominator == 1:
Christian Heimes587c2bf2008-01-19 16:21:02 +000067 if isinstance(numerator, str):
68 # Handle construction from strings.
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000069 m = _RATIONAL_FORMAT.match(numerator)
Christian Heimes587c2bf2008-01-19 16:21:02 +000070 if m is None:
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000071 raise ValueError('Invalid literal for Fraction: %r' %
72 numerator)
73 numerator = int(m.group('num') or '0')
74 denom = m.group('denom')
75 if denom:
76 denominator = int(denom)
Christian Heimesaf98da12008-01-27 15:18:18 +000077 else:
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +000078 denominator = 1
79 decimal = m.group('decimal')
80 if decimal:
81 scale = 10**len(decimal)
82 numerator = numerator * scale + int(decimal)
83 denominator *= scale
84 exp = m.group('exp')
85 if exp:
86 exp = int(exp)
87 if exp >= 0:
88 numerator *= 10**exp
89 else:
90 denominator *= 10**-exp
Christian Heimes587c2bf2008-01-19 16:21:02 +000091 if m.group('sign') == '-':
92 numerator = -numerator
93
Christian Heimes68f5fbe2008-02-14 08:27:37 +000094 elif isinstance(numerator, numbers.Rational):
95 # Handle copies from other rationals. Integrals get
96 # caught here too, but it doesn't matter because
97 # denominator is already 1.
Christian Heimes587c2bf2008-01-19 16:21:02 +000098 other_rational = numerator
99 numerator = other_rational.numerator
100 denominator = other_rational.denominator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000101
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000102 if denominator == 0:
Christian Heimes3feef612008-02-11 06:19:17 +0000103 raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
Georg Brandl86b2fb92008-07-16 03:43:04 +0000104 numerator = operator.index(numerator)
105 denominator = operator.index(denominator)
Christian Heimesaf98da12008-01-27 15:18:18 +0000106 g = gcd(numerator, denominator)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000107 self._numerator = numerator // g
108 self._denominator = denominator // g
Christian Heimes587c2bf2008-01-19 16:21:02 +0000109 return self
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000110
111 @classmethod
112 def from_float(cls, f):
Christian Heimes587c2bf2008-01-19 16:21:02 +0000113 """Converts a finite float to a rational number, exactly.
114
Christian Heimes3feef612008-02-11 06:19:17 +0000115 Beware that Fraction.from_float(0.3) != Fraction(3, 10).
Christian Heimes587c2bf2008-01-19 16:21:02 +0000116
117 """
Georg Brandl2ee470f2008-07-16 12:55:28 +0000118 if isinstance(f, numbers.Integral):
Georg Brandl3a9b0622009-01-03 22:07:57 +0000119 return cls(f)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000120 elif not isinstance(f, float):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000121 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
122 (cls.__name__, f, type(f).__name__))
123 if math.isnan(f) or math.isinf(f):
124 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
Christian Heimes26855632008-01-27 23:50:43 +0000125 return cls(*f.as_integer_ratio())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000126
Christian Heimes587c2bf2008-01-19 16:21:02 +0000127 @classmethod
128 def from_decimal(cls, dec):
129 """Converts a finite Decimal instance to a rational number, exactly."""
130 from decimal import Decimal
Georg Brandl2ee470f2008-07-16 12:55:28 +0000131 if isinstance(dec, numbers.Integral):
132 dec = Decimal(int(dec))
133 elif not isinstance(dec, Decimal):
Christian Heimes587c2bf2008-01-19 16:21:02 +0000134 raise TypeError(
135 "%s.from_decimal() only takes Decimals, not %r (%s)" %
136 (cls.__name__, dec, type(dec).__name__))
137 if not dec.is_finite():
138 # Catches infinities and nans.
139 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
140 sign, digits, exp = dec.as_tuple()
141 digits = int(''.join(map(str, digits)))
142 if sign:
143 digits = -digits
144 if exp >= 0:
145 return cls(digits * 10 ** exp)
146 else:
147 return cls(digits, 10 ** -exp)
148
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000149 def limit_denominator(self, max_denominator=1000000):
150 """Closest Fraction to self with denominator at most max_denominator.
Christian Heimesbbffeb62008-01-24 09:42:52 +0000151
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000152 >>> Fraction('3.141592653589793').limit_denominator(10)
153 Fraction(22, 7)
154 >>> Fraction('3.141592653589793').limit_denominator(100)
155 Fraction(311, 99)
156 >>> Fraction(1234, 5678).limit_denominator(10000)
157 Fraction(1234, 5678)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000158
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000159 """
160 # Algorithm notes: For any real number x, define a *best upper
161 # approximation* to x to be a rational number p/q such that:
162 #
163 # (1) p/q >= x, and
164 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
165 #
166 # Define *best lower approximation* similarly. Then it can be
167 # proved that a rational number is a best upper or lower
168 # approximation to x if, and only if, it is a convergent or
169 # semiconvergent of the (unique shortest) continued fraction
170 # associated to x.
171 #
172 # To find a best rational approximation with denominator <= M,
173 # we find the best upper and lower approximations with
174 # denominator <= M and take whichever of these is closer to x.
175 # In the event of a tie, the bound with smaller denominator is
176 # chosen. If both denominators are equal (which can happen
177 # only when max_denominator == 1 and self is midway between
178 # two integers) the lower bound---i.e., the floor of self, is
179 # taken.
180
181 if max_denominator < 1:
182 raise ValueError("max_denominator should be at least 1")
183 if self._denominator <= max_denominator:
184 return Fraction(self)
185
186 p0, q0, p1, q1 = 0, 1, 1, 0
187 n, d = self._numerator, self._denominator
188 while True:
189 a = n//d
190 q2 = q0+a*q1
191 if q2 > max_denominator:
Christian Heimesbbffeb62008-01-24 09:42:52 +0000192 break
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000193 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
194 n, d = d, n-a*d
195
196 k = (max_denominator-q0)//q1
197 bound1 = Fraction(p0+k*p1, q0+k*q1)
198 bound2 = Fraction(p1, q1)
199 if abs(bound2 - self) <= abs(bound1-self):
200 return bound2
201 else:
202 return bound1
Christian Heimesbbffeb62008-01-24 09:42:52 +0000203
Christian Heimes400adb02008-02-01 08:12:03 +0000204 @property
205 def numerator(a):
206 return a._numerator
207
208 @property
209 def denominator(a):
210 return a._denominator
211
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000212 def __repr__(self):
213 """repr(self)"""
Benjamin Peterson41181742008-07-02 20:22:54 +0000214 return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000215
216 def __str__(self):
217 """str(self)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000218 if self._denominator == 1:
219 return str(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000220 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000221 return '%s/%s' % (self._numerator, self._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000222
223 def _operator_fallbacks(monomorphic_operator, fallback_operator):
224 """Generates forward and reverse operators given a purely-rational
225 operator and a function from the operator module.
226
227 Use this like:
228 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
229
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000230 In general, we want to implement the arithmetic operations so
231 that mixed-mode operations either call an implementation whose
232 author knew about the types of both arguments, or convert both
233 to the nearest built in type and do the operation there. In
Christian Heimes3feef612008-02-11 06:19:17 +0000234 Fraction, that means that we define __add__ and __radd__ as:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000235
236 def __add__(self, other):
Christian Heimes400adb02008-02-01 08:12:03 +0000237 # Both types have numerators/denominator attributes,
238 # so do the operation directly
Christian Heimes3feef612008-02-11 06:19:17 +0000239 if isinstance(other, (int, Fraction)):
240 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000241 other.numerator * self.denominator,
242 self.denominator * other.denominator)
Christian Heimes400adb02008-02-01 08:12:03 +0000243 # float and complex don't have those operations, but we
244 # know about those types, so special case them.
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000245 elif isinstance(other, float):
246 return float(self) + other
247 elif isinstance(other, complex):
248 return complex(self) + other
Christian Heimes400adb02008-02-01 08:12:03 +0000249 # Let the other type take over.
250 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000251
252 def __radd__(self, other):
253 # radd handles more types than add because there's
254 # nothing left to fall back to.
Christian Heimes3feef612008-02-11 06:19:17 +0000255 if isinstance(other, numbers.Rational):
256 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000257 other.numerator * self.denominator,
258 self.denominator * other.denominator)
259 elif isinstance(other, Real):
260 return float(other) + float(self)
261 elif isinstance(other, Complex):
262 return complex(other) + complex(self)
Christian Heimes400adb02008-02-01 08:12:03 +0000263 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000264
265
266 There are 5 different cases for a mixed-type addition on
Christian Heimes3feef612008-02-11 06:19:17 +0000267 Fraction. I'll refer to all of the above code that doesn't
268 refer to Fraction, float, or complex as "boilerplate". 'r'
269 will be an instance of Fraction, which is a subtype of
270 Rational (r : Fraction <: Rational), and b : B <:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000271 Complex. The first three involve 'r + b':
272
Christian Heimes3feef612008-02-11 06:19:17 +0000273 1. If B <: Fraction, int, float, or complex, we handle
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000274 that specially, and all is well.
Christian Heimes3feef612008-02-11 06:19:17 +0000275 2. If Fraction falls back to the boilerplate code, and it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000276 were to return a value from __add__, we'd miss the
277 possibility that B defines a more intelligent __radd__,
278 so the boilerplate should return NotImplemented from
Christian Heimes3feef612008-02-11 06:19:17 +0000279 __add__. In particular, we don't handle Rational
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000280 here, even though we could get an exact answer, in case
281 the other type wants to do something special.
Christian Heimes3feef612008-02-11 06:19:17 +0000282 3. If B <: Fraction, Python tries B.__radd__ before
283 Fraction.__add__. This is ok, because it was
284 implemented with knowledge of Fraction, so it can
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000285 handle those instances before delegating to Real or
286 Complex.
287
288 The next two situations describe 'b + r'. We assume that b
Christian Heimes3feef612008-02-11 06:19:17 +0000289 didn't know about Fraction in its implementation, and that it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000290 uses similar boilerplate code:
291
Christian Heimes3feef612008-02-11 06:19:17 +0000292 4. If B <: Rational, then __radd_ converts both to the
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000293 builtin rational type (hey look, that's us) and
294 proceeds.
295 5. Otherwise, __radd__ tries to find the nearest common
296 base ABC, and fall back to its builtin type. Since this
297 class doesn't subclass a concrete type, there's no
298 implementation to fall back to, so we need to try as
299 hard as possible to return an actual value, or the user
300 will get a TypeError.
301
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000302 """
303 def forward(a, b):
Christian Heimes3feef612008-02-11 06:19:17 +0000304 if isinstance(b, (int, Fraction)):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000305 return monomorphic_operator(a, b)
306 elif isinstance(b, float):
307 return fallback_operator(float(a), b)
308 elif isinstance(b, complex):
309 return fallback_operator(complex(a), b)
310 else:
311 return NotImplemented
312 forward.__name__ = '__' + fallback_operator.__name__ + '__'
313 forward.__doc__ = monomorphic_operator.__doc__
314
315 def reverse(b, a):
Christian Heimes3feef612008-02-11 06:19:17 +0000316 if isinstance(a, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000317 # Includes ints.
318 return monomorphic_operator(a, b)
319 elif isinstance(a, numbers.Real):
320 return fallback_operator(float(a), float(b))
321 elif isinstance(a, numbers.Complex):
322 return fallback_operator(complex(a), complex(b))
323 else:
324 return NotImplemented
325 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
326 reverse.__doc__ = monomorphic_operator.__doc__
327
328 return forward, reverse
329
330 def _add(a, b):
331 """a + b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000332 return Fraction(a.numerator * b.denominator +
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000333 b.numerator * a.denominator,
334 a.denominator * b.denominator)
335
336 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
337
338 def _sub(a, b):
339 """a - b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000340 return Fraction(a.numerator * b.denominator -
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000341 b.numerator * a.denominator,
342 a.denominator * b.denominator)
343
344 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
345
346 def _mul(a, b):
347 """a * b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000348 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000349
350 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
351
352 def _div(a, b):
353 """a / b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000354 return Fraction(a.numerator * b.denominator,
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000355 a.denominator * b.numerator)
356
357 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000358
359 def __floordiv__(a, b):
360 """a // b"""
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000361 return math.floor(a / b)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000362
363 def __rfloordiv__(b, a):
364 """a // b"""
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000365 return math.floor(a / b)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000366
Christian Heimes969fe572008-01-25 11:23:10 +0000367 def __mod__(a, b):
368 """a % b"""
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000369 div = a // b
370 return a - b * div
371
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000372 def __rmod__(b, a):
373 """a % b"""
Christian Heimes969fe572008-01-25 11:23:10 +0000374 div = a // b
375 return a - b * div
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000376
377 def __pow__(a, b):
378 """a ** b
379
380 If b is not an integer, the result will be a float or complex
381 since roots are generally irrational. If b is an integer, the
382 result will be rational.
383
384 """
Christian Heimes3feef612008-02-11 06:19:17 +0000385 if isinstance(b, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000386 if b.denominator == 1:
387 power = b.numerator
388 if power >= 0:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000389 return Fraction(a._numerator ** power,
390 a._denominator ** power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000391 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000392 return Fraction(a._denominator ** -power,
393 a._numerator ** -power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000394 else:
395 # A fractional power will generally produce an
396 # irrational number.
397 return float(a) ** float(b)
398 else:
399 return float(a) ** b
400
401 def __rpow__(b, a):
402 """a ** b"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000403 if b._denominator == 1 and b._numerator >= 0:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000404 # If a is an int, keep it that way if possible.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000405 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000406
Christian Heimes3feef612008-02-11 06:19:17 +0000407 if isinstance(a, numbers.Rational):
408 return Fraction(a.numerator, a.denominator) ** b
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000409
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000410 if b._denominator == 1:
411 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000412
413 return a ** float(b)
414
415 def __pos__(a):
Christian Heimes3feef612008-02-11 06:19:17 +0000416 """+a: Coerces a subclass instance to Fraction"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000417 return Fraction(a._numerator, a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000418
419 def __neg__(a):
420 """-a"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000421 return Fraction(-a._numerator, a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000422
423 def __abs__(a):
424 """abs(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000425 return Fraction(abs(a._numerator), a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000426
427 def __trunc__(a):
428 """trunc(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000429 if a._numerator < 0:
430 return -(-a._numerator // a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000431 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000432 return a._numerator // a._denominator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000433
434 def __floor__(a):
435 """Will be math.floor(a) in 3.0."""
436 return a.numerator // a.denominator
437
438 def __ceil__(a):
439 """Will be math.ceil(a) in 3.0."""
440 # The negations cleverly convince floordiv to return the ceiling.
441 return -(-a.numerator // a.denominator)
442
443 def __round__(self, ndigits=None):
444 """Will be round(self, ndigits) in 3.0.
445
446 Rounds half toward even.
447 """
448 if ndigits is None:
449 floor, remainder = divmod(self.numerator, self.denominator)
450 if remainder * 2 < self.denominator:
451 return floor
452 elif remainder * 2 > self.denominator:
453 return floor + 1
454 # Deal with the half case:
455 elif floor % 2 == 0:
456 return floor
457 else:
458 return floor + 1
459 shift = 10**abs(ndigits)
460 # See _operator_fallbacks.forward to check that the results of
Christian Heimes3feef612008-02-11 06:19:17 +0000461 # these operations will always be Fraction and therefore have
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000462 # round().
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000463 if ndigits > 0:
Christian Heimes3feef612008-02-11 06:19:17 +0000464 return Fraction(round(self * shift), shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000465 else:
Christian Heimes3feef612008-02-11 06:19:17 +0000466 return Fraction(round(self / shift) * shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000467
468 def __hash__(self):
469 """hash(self)
470
471 Tricky because values that are exactly representable as a
472 float must have the same hash as that float.
473
474 """
Christian Heimes969fe572008-01-25 11:23:10 +0000475 # XXX since this method is expensive, consider caching the result
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000476 if self._denominator == 1:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000477 # Get integers right.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000478 return hash(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000479 # Expensive check, but definitely correct.
480 if self == float(self):
481 return hash(float(self))
482 else:
483 # Use tuple's hash to avoid a high collision rate on
484 # simple fractions.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000485 return hash((self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000486
487 def __eq__(a, b):
488 """a == b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000489 if isinstance(b, numbers.Rational):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000490 return (a._numerator == b.numerator and
491 a._denominator == b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000492 if isinstance(b, numbers.Complex) and b.imag == 0:
493 b = b.real
494 if isinstance(b, float):
495 return a == a.from_float(b)
496 else:
497 # XXX: If b.__eq__ is implemented like this method, it may
498 # give the wrong answer after float(a) changes a's
499 # value. Better ways of doing this are welcome.
500 return float(a) == b
501
502 def _subtractAndCompareToZero(a, b, op):
503 """Helper function for comparison operators.
504
505 Subtracts b from a, exactly if possible, and compares the
506 result with 0 using op, in such a way that the comparison
507 won't recurse. If the difference raises a TypeError, returns
508 NotImplemented instead.
509
510 """
511 if isinstance(b, numbers.Complex) and b.imag == 0:
512 b = b.real
513 if isinstance(b, float):
514 b = a.from_float(b)
515 try:
Christian Heimes3feef612008-02-11 06:19:17 +0000516 # XXX: If b <: Real but not <: Rational, this is likely
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000517 # to fall back to a float. If the actual values differ by
518 # less than MIN_FLOAT, this could falsely call them equal,
519 # which would make <= inconsistent with ==. Better ways of
520 # doing this are welcome.
521 diff = a - b
522 except TypeError:
523 return NotImplemented
Christian Heimes3feef612008-02-11 06:19:17 +0000524 if isinstance(diff, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000525 return op(diff.numerator, 0)
526 return op(diff, 0)
527
528 def __lt__(a, b):
529 """a < b"""
530 return a._subtractAndCompareToZero(b, operator.lt)
531
532 def __gt__(a, b):
533 """a > b"""
534 return a._subtractAndCompareToZero(b, operator.gt)
535
536 def __le__(a, b):
537 """a <= b"""
538 return a._subtractAndCompareToZero(b, operator.le)
539
540 def __ge__(a, b):
541 """a >= b"""
542 return a._subtractAndCompareToZero(b, operator.ge)
543
544 def __bool__(a):
545 """a != 0"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000546 return a._numerator != 0
Christian Heimes969fe572008-01-25 11:23:10 +0000547
548 # support for pickling, copy, and deepcopy
549
550 def __reduce__(self):
551 return (self.__class__, (str(self),))
552
553 def __copy__(self):
Christian Heimes3feef612008-02-11 06:19:17 +0000554 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000555 return self # I'm immutable; therefore I am my own clone
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000556 return self.__class__(self._numerator, self._denominator)
Christian Heimes969fe572008-01-25 11:23:10 +0000557
558 def __deepcopy__(self, memo):
Christian Heimes3feef612008-02-11 06:19:17 +0000559 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000560 return self # My components are also immutable
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000561 return self.__class__(self._numerator, self._denominator)