blob: 3df628adc0b98fadcc3e7b2c899e644ea588ad12 [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)
31 (?: # followed by an optional
32 /(?P<denom>\d+) # / and denominator
33 | # or
34 \.(?P<decimal>\d*) # decimal point and fractional part
35 )?
36 \s*\Z # and optional whitespace to finish
37""", re.VERBOSE)
Christian Heimes587c2bf2008-01-19 16:21:02 +000038
39
Christian Heimes3feef612008-02-11 06:19:17 +000040class Fraction(numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +000041 """This class implements rational numbers.
42
Christian Heimes3feef612008-02-11 06:19:17 +000043 Fraction(8, 6) will produce a rational number equivalent to
Guido van Rossum7736b5b2008-01-15 21:44:53 +000044 4/3. Both arguments must be Integral. The numerator defaults to 0
Christian Heimes3feef612008-02-11 06:19:17 +000045 and the denominator defaults to 1 so that Fraction(3) == 3 and
46 Fraction() == 0.
Guido van Rossum7736b5b2008-01-15 21:44:53 +000047
Christian Heimes3feef612008-02-11 06:19:17 +000048 Fraction can also be constructed from strings of the form
Christian Heimesaf98da12008-01-27 15:18:18 +000049 '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
Christian Heimes587c2bf2008-01-19 16:21:02 +000050
Guido van Rossum7736b5b2008-01-15 21:44:53 +000051 """
52
Christian Heimes400adb02008-02-01 08:12:03 +000053 __slots__ = ('_numerator', '_denominator')
Guido van Rossum7736b5b2008-01-15 21:44:53 +000054
Christian Heimes587c2bf2008-01-19 16:21:02 +000055 # We're immutable, so use __new__ not __init__
56 def __new__(cls, numerator=0, denominator=1):
57 """Constructs a Rational.
58
Christian Heimesaf98da12008-01-27 15:18:18 +000059 Takes a string like '3/2' or '1.5', another Rational, or a
60 numerator/denominator pair.
Christian Heimes587c2bf2008-01-19 16:21:02 +000061
62 """
Christian Heimes3feef612008-02-11 06:19:17 +000063 self = super(Fraction, cls).__new__(cls)
Christian Heimes587c2bf2008-01-19 16:21:02 +000064
Christian Heimes68f5fbe2008-02-14 08:27:37 +000065 if not isinstance(numerator, int) and denominator == 1:
Christian Heimes587c2bf2008-01-19 16:21:02 +000066 if isinstance(numerator, str):
67 # Handle construction from strings.
68 input = numerator
69 m = _RATIONAL_FORMAT.match(input)
70 if m is None:
Benjamin Petersondcf97b92008-07-02 17:30:14 +000071 raise ValueError('Invalid literal for Fraction: %r' % input)
Christian Heimesaf98da12008-01-27 15:18:18 +000072 numerator = m.group('num')
73 decimal = m.group('decimal')
74 if decimal:
75 # The literal is a decimal number.
76 numerator = int(numerator + decimal)
77 denominator = 10**len(decimal)
78 else:
79 # The literal is an integer or fraction.
80 numerator = int(numerator)
81 # Default denominator to 1.
82 denominator = int(m.group('denom') or 1)
83
Christian Heimes587c2bf2008-01-19 16:21:02 +000084 if m.group('sign') == '-':
85 numerator = -numerator
86
Christian Heimes68f5fbe2008-02-14 08:27:37 +000087 elif isinstance(numerator, numbers.Rational):
88 # Handle copies from other rationals. Integrals get
89 # caught here too, but it doesn't matter because
90 # denominator is already 1.
Christian Heimes587c2bf2008-01-19 16:21:02 +000091 other_rational = numerator
92 numerator = other_rational.numerator
93 denominator = other_rational.denominator
Guido van Rossum7736b5b2008-01-15 21:44:53 +000094
Guido van Rossum7736b5b2008-01-15 21:44:53 +000095 if denominator == 0:
Christian Heimes3feef612008-02-11 06:19:17 +000096 raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
Georg Brandl86b2fb92008-07-16 03:43:04 +000097 numerator = operator.index(numerator)
98 denominator = operator.index(denominator)
Christian Heimesaf98da12008-01-27 15:18:18 +000099 g = gcd(numerator, denominator)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000100 self._numerator = numerator // g
101 self._denominator = denominator // g
Christian Heimes587c2bf2008-01-19 16:21:02 +0000102 return self
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000103
104 @classmethod
105 def from_float(cls, f):
Christian Heimes587c2bf2008-01-19 16:21:02 +0000106 """Converts a finite float to a rational number, exactly.
107
Christian Heimes3feef612008-02-11 06:19:17 +0000108 Beware that Fraction.from_float(0.3) != Fraction(3, 10).
Christian Heimes587c2bf2008-01-19 16:21:02 +0000109
110 """
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000111 if not isinstance(f, float):
112 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
113 (cls.__name__, f, type(f).__name__))
114 if math.isnan(f) or math.isinf(f):
115 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
Christian Heimes26855632008-01-27 23:50:43 +0000116 return cls(*f.as_integer_ratio())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000117
Christian Heimes587c2bf2008-01-19 16:21:02 +0000118 @classmethod
119 def from_decimal(cls, dec):
120 """Converts a finite Decimal instance to a rational number, exactly."""
121 from decimal import Decimal
122 if not isinstance(dec, Decimal):
123 raise TypeError(
124 "%s.from_decimal() only takes Decimals, not %r (%s)" %
125 (cls.__name__, dec, type(dec).__name__))
126 if not dec.is_finite():
127 # Catches infinities and nans.
128 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
129 sign, digits, exp = dec.as_tuple()
130 digits = int(''.join(map(str, digits)))
131 if sign:
132 digits = -digits
133 if exp >= 0:
134 return cls(digits * 10 ** exp)
135 else:
136 return cls(digits, 10 ** -exp)
137
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000138 def limit_denominator(self, max_denominator=1000000):
139 """Closest Fraction to self with denominator at most max_denominator.
Christian Heimesbbffeb62008-01-24 09:42:52 +0000140
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000141 >>> Fraction('3.141592653589793').limit_denominator(10)
142 Fraction(22, 7)
143 >>> Fraction('3.141592653589793').limit_denominator(100)
144 Fraction(311, 99)
145 >>> Fraction(1234, 5678).limit_denominator(10000)
146 Fraction(1234, 5678)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000147
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000148 """
149 # Algorithm notes: For any real number x, define a *best upper
150 # approximation* to x to be a rational number p/q such that:
151 #
152 # (1) p/q >= x, and
153 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
154 #
155 # Define *best lower approximation* similarly. Then it can be
156 # proved that a rational number is a best upper or lower
157 # approximation to x if, and only if, it is a convergent or
158 # semiconvergent of the (unique shortest) continued fraction
159 # associated to x.
160 #
161 # To find a best rational approximation with denominator <= M,
162 # we find the best upper and lower approximations with
163 # denominator <= M and take whichever of these is closer to x.
164 # In the event of a tie, the bound with smaller denominator is
165 # chosen. If both denominators are equal (which can happen
166 # only when max_denominator == 1 and self is midway between
167 # two integers) the lower bound---i.e., the floor of self, is
168 # taken.
169
170 if max_denominator < 1:
171 raise ValueError("max_denominator should be at least 1")
172 if self._denominator <= max_denominator:
173 return Fraction(self)
174
175 p0, q0, p1, q1 = 0, 1, 1, 0
176 n, d = self._numerator, self._denominator
177 while True:
178 a = n//d
179 q2 = q0+a*q1
180 if q2 > max_denominator:
Christian Heimesbbffeb62008-01-24 09:42:52 +0000181 break
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000182 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
183 n, d = d, n-a*d
184
185 k = (max_denominator-q0)//q1
186 bound1 = Fraction(p0+k*p1, q0+k*q1)
187 bound2 = Fraction(p1, q1)
188 if abs(bound2 - self) <= abs(bound1-self):
189 return bound2
190 else:
191 return bound1
Christian Heimesbbffeb62008-01-24 09:42:52 +0000192
Christian Heimes400adb02008-02-01 08:12:03 +0000193 @property
194 def numerator(a):
195 return a._numerator
196
197 @property
198 def denominator(a):
199 return a._denominator
200
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000201 def __repr__(self):
202 """repr(self)"""
Benjamin Peterson41181742008-07-02 20:22:54 +0000203 return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000204
205 def __str__(self):
206 """str(self)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000207 if self._denominator == 1:
208 return str(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000209 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000210 return '%s/%s' % (self._numerator, self._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000211
212 def _operator_fallbacks(monomorphic_operator, fallback_operator):
213 """Generates forward and reverse operators given a purely-rational
214 operator and a function from the operator module.
215
216 Use this like:
217 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
218
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000219 In general, we want to implement the arithmetic operations so
220 that mixed-mode operations either call an implementation whose
221 author knew about the types of both arguments, or convert both
222 to the nearest built in type and do the operation there. In
Christian Heimes3feef612008-02-11 06:19:17 +0000223 Fraction, that means that we define __add__ and __radd__ as:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000224
225 def __add__(self, other):
Christian Heimes400adb02008-02-01 08:12:03 +0000226 # Both types have numerators/denominator attributes,
227 # so do the operation directly
Christian Heimes3feef612008-02-11 06:19:17 +0000228 if isinstance(other, (int, Fraction)):
229 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000230 other.numerator * self.denominator,
231 self.denominator * other.denominator)
Christian Heimes400adb02008-02-01 08:12:03 +0000232 # float and complex don't have those operations, but we
233 # know about those types, so special case them.
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000234 elif isinstance(other, float):
235 return float(self) + other
236 elif isinstance(other, complex):
237 return complex(self) + other
Christian Heimes400adb02008-02-01 08:12:03 +0000238 # Let the other type take over.
239 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000240
241 def __radd__(self, other):
242 # radd handles more types than add because there's
243 # nothing left to fall back to.
Christian Heimes3feef612008-02-11 06:19:17 +0000244 if isinstance(other, numbers.Rational):
245 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000246 other.numerator * self.denominator,
247 self.denominator * other.denominator)
248 elif isinstance(other, Real):
249 return float(other) + float(self)
250 elif isinstance(other, Complex):
251 return complex(other) + complex(self)
Christian Heimes400adb02008-02-01 08:12:03 +0000252 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000253
254
255 There are 5 different cases for a mixed-type addition on
Christian Heimes3feef612008-02-11 06:19:17 +0000256 Fraction. I'll refer to all of the above code that doesn't
257 refer to Fraction, float, or complex as "boilerplate". 'r'
258 will be an instance of Fraction, which is a subtype of
259 Rational (r : Fraction <: Rational), and b : B <:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000260 Complex. The first three involve 'r + b':
261
Christian Heimes3feef612008-02-11 06:19:17 +0000262 1. If B <: Fraction, int, float, or complex, we handle
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000263 that specially, and all is well.
Christian Heimes3feef612008-02-11 06:19:17 +0000264 2. If Fraction falls back to the boilerplate code, and it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000265 were to return a value from __add__, we'd miss the
266 possibility that B defines a more intelligent __radd__,
267 so the boilerplate should return NotImplemented from
Christian Heimes3feef612008-02-11 06:19:17 +0000268 __add__. In particular, we don't handle Rational
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000269 here, even though we could get an exact answer, in case
270 the other type wants to do something special.
Christian Heimes3feef612008-02-11 06:19:17 +0000271 3. If B <: Fraction, Python tries B.__radd__ before
272 Fraction.__add__. This is ok, because it was
273 implemented with knowledge of Fraction, so it can
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000274 handle those instances before delegating to Real or
275 Complex.
276
277 The next two situations describe 'b + r'. We assume that b
Christian Heimes3feef612008-02-11 06:19:17 +0000278 didn't know about Fraction in its implementation, and that it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000279 uses similar boilerplate code:
280
Christian Heimes3feef612008-02-11 06:19:17 +0000281 4. If B <: Rational, then __radd_ converts both to the
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000282 builtin rational type (hey look, that's us) and
283 proceeds.
284 5. Otherwise, __radd__ tries to find the nearest common
285 base ABC, and fall back to its builtin type. Since this
286 class doesn't subclass a concrete type, there's no
287 implementation to fall back to, so we need to try as
288 hard as possible to return an actual value, or the user
289 will get a TypeError.
290
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000291 """
292 def forward(a, b):
Christian Heimes3feef612008-02-11 06:19:17 +0000293 if isinstance(b, (int, Fraction)):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000294 return monomorphic_operator(a, b)
295 elif isinstance(b, float):
296 return fallback_operator(float(a), b)
297 elif isinstance(b, complex):
298 return fallback_operator(complex(a), b)
299 else:
300 return NotImplemented
301 forward.__name__ = '__' + fallback_operator.__name__ + '__'
302 forward.__doc__ = monomorphic_operator.__doc__
303
304 def reverse(b, a):
Christian Heimes3feef612008-02-11 06:19:17 +0000305 if isinstance(a, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000306 # Includes ints.
307 return monomorphic_operator(a, b)
308 elif isinstance(a, numbers.Real):
309 return fallback_operator(float(a), float(b))
310 elif isinstance(a, numbers.Complex):
311 return fallback_operator(complex(a), complex(b))
312 else:
313 return NotImplemented
314 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
315 reverse.__doc__ = monomorphic_operator.__doc__
316
317 return forward, reverse
318
319 def _add(a, b):
320 """a + b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000321 return Fraction(a.numerator * b.denominator +
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000322 b.numerator * a.denominator,
323 a.denominator * b.denominator)
324
325 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
326
327 def _sub(a, b):
328 """a - b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000329 return Fraction(a.numerator * b.denominator -
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000330 b.numerator * a.denominator,
331 a.denominator * b.denominator)
332
333 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
334
335 def _mul(a, b):
336 """a * b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000337 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000338
339 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
340
341 def _div(a, b):
342 """a / b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000343 return Fraction(a.numerator * b.denominator,
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000344 a.denominator * b.numerator)
345
346 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000347
348 def __floordiv__(a, b):
349 """a // b"""
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000350 return math.floor(a / b)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000351
352 def __rfloordiv__(b, a):
353 """a // b"""
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000354 return math.floor(a / b)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000355
Christian Heimes969fe572008-01-25 11:23:10 +0000356 def __mod__(a, b):
357 """a % b"""
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000358 div = a // b
359 return a - b * div
360
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000361 def __rmod__(b, a):
362 """a % b"""
Christian Heimes969fe572008-01-25 11:23:10 +0000363 div = a // b
364 return a - b * div
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000365
366 def __pow__(a, b):
367 """a ** b
368
369 If b is not an integer, the result will be a float or complex
370 since roots are generally irrational. If b is an integer, the
371 result will be rational.
372
373 """
Christian Heimes3feef612008-02-11 06:19:17 +0000374 if isinstance(b, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000375 if b.denominator == 1:
376 power = b.numerator
377 if power >= 0:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000378 return Fraction(a._numerator ** power,
379 a._denominator ** power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000380 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000381 return Fraction(a._denominator ** -power,
382 a._numerator ** -power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000383 else:
384 # A fractional power will generally produce an
385 # irrational number.
386 return float(a) ** float(b)
387 else:
388 return float(a) ** b
389
390 def __rpow__(b, a):
391 """a ** b"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000392 if b._denominator == 1 and b._numerator >= 0:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000393 # If a is an int, keep it that way if possible.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000394 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000395
Christian Heimes3feef612008-02-11 06:19:17 +0000396 if isinstance(a, numbers.Rational):
397 return Fraction(a.numerator, a.denominator) ** b
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000398
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000399 if b._denominator == 1:
400 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000401
402 return a ** float(b)
403
404 def __pos__(a):
Christian Heimes3feef612008-02-11 06:19:17 +0000405 """+a: Coerces a subclass instance to Fraction"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000406 return Fraction(a._numerator, a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000407
408 def __neg__(a):
409 """-a"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000410 return Fraction(-a._numerator, a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000411
412 def __abs__(a):
413 """abs(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000414 return Fraction(abs(a._numerator), a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000415
416 def __trunc__(a):
417 """trunc(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000418 if a._numerator < 0:
419 return -(-a._numerator // a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000420 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000421 return a._numerator // a._denominator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000422
423 def __floor__(a):
424 """Will be math.floor(a) in 3.0."""
425 return a.numerator // a.denominator
426
427 def __ceil__(a):
428 """Will be math.ceil(a) in 3.0."""
429 # The negations cleverly convince floordiv to return the ceiling.
430 return -(-a.numerator // a.denominator)
431
432 def __round__(self, ndigits=None):
433 """Will be round(self, ndigits) in 3.0.
434
435 Rounds half toward even.
436 """
437 if ndigits is None:
438 floor, remainder = divmod(self.numerator, self.denominator)
439 if remainder * 2 < self.denominator:
440 return floor
441 elif remainder * 2 > self.denominator:
442 return floor + 1
443 # Deal with the half case:
444 elif floor % 2 == 0:
445 return floor
446 else:
447 return floor + 1
448 shift = 10**abs(ndigits)
449 # See _operator_fallbacks.forward to check that the results of
Christian Heimes3feef612008-02-11 06:19:17 +0000450 # these operations will always be Fraction and therefore have
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000451 # round().
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000452 if ndigits > 0:
Christian Heimes3feef612008-02-11 06:19:17 +0000453 return Fraction(round(self * shift), shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000454 else:
Christian Heimes3feef612008-02-11 06:19:17 +0000455 return Fraction(round(self / shift) * shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000456
457 def __hash__(self):
458 """hash(self)
459
460 Tricky because values that are exactly representable as a
461 float must have the same hash as that float.
462
463 """
Christian Heimes969fe572008-01-25 11:23:10 +0000464 # XXX since this method is expensive, consider caching the result
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000465 if self._denominator == 1:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000466 # Get integers right.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000467 return hash(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000468 # Expensive check, but definitely correct.
469 if self == float(self):
470 return hash(float(self))
471 else:
472 # Use tuple's hash to avoid a high collision rate on
473 # simple fractions.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000474 return hash((self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000475
476 def __eq__(a, b):
477 """a == b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000478 if isinstance(b, numbers.Rational):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000479 return (a._numerator == b.numerator and
480 a._denominator == b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000481 if isinstance(b, numbers.Complex) and b.imag == 0:
482 b = b.real
483 if isinstance(b, float):
484 return a == a.from_float(b)
485 else:
486 # XXX: If b.__eq__ is implemented like this method, it may
487 # give the wrong answer after float(a) changes a's
488 # value. Better ways of doing this are welcome.
489 return float(a) == b
490
491 def _subtractAndCompareToZero(a, b, op):
492 """Helper function for comparison operators.
493
494 Subtracts b from a, exactly if possible, and compares the
495 result with 0 using op, in such a way that the comparison
496 won't recurse. If the difference raises a TypeError, returns
497 NotImplemented instead.
498
499 """
500 if isinstance(b, numbers.Complex) and b.imag == 0:
501 b = b.real
502 if isinstance(b, float):
503 b = a.from_float(b)
504 try:
Christian Heimes3feef612008-02-11 06:19:17 +0000505 # XXX: If b <: Real but not <: Rational, this is likely
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000506 # to fall back to a float. If the actual values differ by
507 # less than MIN_FLOAT, this could falsely call them equal,
508 # which would make <= inconsistent with ==. Better ways of
509 # doing this are welcome.
510 diff = a - b
511 except TypeError:
512 return NotImplemented
Christian Heimes3feef612008-02-11 06:19:17 +0000513 if isinstance(diff, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000514 return op(diff.numerator, 0)
515 return op(diff, 0)
516
517 def __lt__(a, b):
518 """a < b"""
519 return a._subtractAndCompareToZero(b, operator.lt)
520
521 def __gt__(a, b):
522 """a > b"""
523 return a._subtractAndCompareToZero(b, operator.gt)
524
525 def __le__(a, b):
526 """a <= b"""
527 return a._subtractAndCompareToZero(b, operator.le)
528
529 def __ge__(a, b):
530 """a >= b"""
531 return a._subtractAndCompareToZero(b, operator.ge)
532
533 def __bool__(a):
534 """a != 0"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000535 return a._numerator != 0
Christian Heimes969fe572008-01-25 11:23:10 +0000536
537 # support for pickling, copy, and deepcopy
538
539 def __reduce__(self):
540 return (self.__class__, (str(self),))
541
542 def __copy__(self):
Christian Heimes3feef612008-02-11 06:19:17 +0000543 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000544 return self # I'm immutable; therefore I am my own clone
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000545 return self.__class__(self._numerator, self._denominator)
Christian Heimes969fe572008-01-25 11:23:10 +0000546
547 def __deepcopy__(self, memo):
Christian Heimes3feef612008-02-11 06:19:17 +0000548 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000549 return self # My components are also immutable
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000550 return self.__class__(self._numerator, self._denominator)