blob: ed1e9a0c1035e570366840efbf0405172a724117 [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 """
Georg Brandl2ee470f2008-07-16 12:55:28 +0000111 if isinstance(f, numbers.Integral):
Georg Brandl3a9b0622009-01-03 22:07:57 +0000112 return cls(f)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000113 elif not isinstance(f, float):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000114 raise TypeError("%s.from_float() only takes floats, not %r (%s)" %
115 (cls.__name__, f, type(f).__name__))
116 if math.isnan(f) or math.isinf(f):
117 raise TypeError("Cannot convert %r to %s." % (f, cls.__name__))
Christian Heimes26855632008-01-27 23:50:43 +0000118 return cls(*f.as_integer_ratio())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000119
Christian Heimes587c2bf2008-01-19 16:21:02 +0000120 @classmethod
121 def from_decimal(cls, dec):
122 """Converts a finite Decimal instance to a rational number, exactly."""
123 from decimal import Decimal
Georg Brandl2ee470f2008-07-16 12:55:28 +0000124 if isinstance(dec, numbers.Integral):
125 dec = Decimal(int(dec))
126 elif not isinstance(dec, Decimal):
Christian Heimes587c2bf2008-01-19 16:21:02 +0000127 raise TypeError(
128 "%s.from_decimal() only takes Decimals, not %r (%s)" %
129 (cls.__name__, dec, type(dec).__name__))
130 if not dec.is_finite():
131 # Catches infinities and nans.
132 raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__))
133 sign, digits, exp = dec.as_tuple()
134 digits = int(''.join(map(str, digits)))
135 if sign:
136 digits = -digits
137 if exp >= 0:
138 return cls(digits * 10 ** exp)
139 else:
140 return cls(digits, 10 ** -exp)
141
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000142 def limit_denominator(self, max_denominator=1000000):
143 """Closest Fraction to self with denominator at most max_denominator.
Christian Heimesbbffeb62008-01-24 09:42:52 +0000144
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000145 >>> Fraction('3.141592653589793').limit_denominator(10)
146 Fraction(22, 7)
147 >>> Fraction('3.141592653589793').limit_denominator(100)
148 Fraction(311, 99)
149 >>> Fraction(1234, 5678).limit_denominator(10000)
150 Fraction(1234, 5678)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000151
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000152 """
153 # Algorithm notes: For any real number x, define a *best upper
154 # approximation* to x to be a rational number p/q such that:
155 #
156 # (1) p/q >= x, and
157 # (2) if p/q > r/s >= x then s > q, for any rational r/s.
158 #
159 # Define *best lower approximation* similarly. Then it can be
160 # proved that a rational number is a best upper or lower
161 # approximation to x if, and only if, it is a convergent or
162 # semiconvergent of the (unique shortest) continued fraction
163 # associated to x.
164 #
165 # To find a best rational approximation with denominator <= M,
166 # we find the best upper and lower approximations with
167 # denominator <= M and take whichever of these is closer to x.
168 # In the event of a tie, the bound with smaller denominator is
169 # chosen. If both denominators are equal (which can happen
170 # only when max_denominator == 1 and self is midway between
171 # two integers) the lower bound---i.e., the floor of self, is
172 # taken.
173
174 if max_denominator < 1:
175 raise ValueError("max_denominator should be at least 1")
176 if self._denominator <= max_denominator:
177 return Fraction(self)
178
179 p0, q0, p1, q1 = 0, 1, 1, 0
180 n, d = self._numerator, self._denominator
181 while True:
182 a = n//d
183 q2 = q0+a*q1
184 if q2 > max_denominator:
Christian Heimesbbffeb62008-01-24 09:42:52 +0000185 break
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000186 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
187 n, d = d, n-a*d
188
189 k = (max_denominator-q0)//q1
190 bound1 = Fraction(p0+k*p1, q0+k*q1)
191 bound2 = Fraction(p1, q1)
192 if abs(bound2 - self) <= abs(bound1-self):
193 return bound2
194 else:
195 return bound1
Christian Heimesbbffeb62008-01-24 09:42:52 +0000196
Christian Heimes400adb02008-02-01 08:12:03 +0000197 @property
198 def numerator(a):
199 return a._numerator
200
201 @property
202 def denominator(a):
203 return a._denominator
204
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000205 def __repr__(self):
206 """repr(self)"""
Benjamin Peterson41181742008-07-02 20:22:54 +0000207 return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000208
209 def __str__(self):
210 """str(self)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000211 if self._denominator == 1:
212 return str(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000213 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000214 return '%s/%s' % (self._numerator, self._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000215
216 def _operator_fallbacks(monomorphic_operator, fallback_operator):
217 """Generates forward and reverse operators given a purely-rational
218 operator and a function from the operator module.
219
220 Use this like:
221 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
222
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000223 In general, we want to implement the arithmetic operations so
224 that mixed-mode operations either call an implementation whose
225 author knew about the types of both arguments, or convert both
226 to the nearest built in type and do the operation there. In
Christian Heimes3feef612008-02-11 06:19:17 +0000227 Fraction, that means that we define __add__ and __radd__ as:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000228
229 def __add__(self, other):
Christian Heimes400adb02008-02-01 08:12:03 +0000230 # Both types have numerators/denominator attributes,
231 # so do the operation directly
Christian Heimes3feef612008-02-11 06:19:17 +0000232 if isinstance(other, (int, Fraction)):
233 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000234 other.numerator * self.denominator,
235 self.denominator * other.denominator)
Christian Heimes400adb02008-02-01 08:12:03 +0000236 # float and complex don't have those operations, but we
237 # know about those types, so special case them.
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000238 elif isinstance(other, float):
239 return float(self) + other
240 elif isinstance(other, complex):
241 return complex(self) + other
Christian Heimes400adb02008-02-01 08:12:03 +0000242 # Let the other type take over.
243 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000244
245 def __radd__(self, other):
246 # radd handles more types than add because there's
247 # nothing left to fall back to.
Christian Heimes3feef612008-02-11 06:19:17 +0000248 if isinstance(other, numbers.Rational):
249 return Fraction(self.numerator * other.denominator +
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000250 other.numerator * self.denominator,
251 self.denominator * other.denominator)
252 elif isinstance(other, Real):
253 return float(other) + float(self)
254 elif isinstance(other, Complex):
255 return complex(other) + complex(self)
Christian Heimes400adb02008-02-01 08:12:03 +0000256 return NotImplemented
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000257
258
259 There are 5 different cases for a mixed-type addition on
Christian Heimes3feef612008-02-11 06:19:17 +0000260 Fraction. I'll refer to all of the above code that doesn't
261 refer to Fraction, float, or complex as "boilerplate". 'r'
262 will be an instance of Fraction, which is a subtype of
263 Rational (r : Fraction <: Rational), and b : B <:
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000264 Complex. The first three involve 'r + b':
265
Christian Heimes3feef612008-02-11 06:19:17 +0000266 1. If B <: Fraction, int, float, or complex, we handle
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000267 that specially, and all is well.
Christian Heimes3feef612008-02-11 06:19:17 +0000268 2. If Fraction falls back to the boilerplate code, and it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000269 were to return a value from __add__, we'd miss the
270 possibility that B defines a more intelligent __radd__,
271 so the boilerplate should return NotImplemented from
Christian Heimes3feef612008-02-11 06:19:17 +0000272 __add__. In particular, we don't handle Rational
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000273 here, even though we could get an exact answer, in case
274 the other type wants to do something special.
Christian Heimes3feef612008-02-11 06:19:17 +0000275 3. If B <: Fraction, Python tries B.__radd__ before
276 Fraction.__add__. This is ok, because it was
277 implemented with knowledge of Fraction, so it can
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000278 handle those instances before delegating to Real or
279 Complex.
280
281 The next two situations describe 'b + r'. We assume that b
Christian Heimes3feef612008-02-11 06:19:17 +0000282 didn't know about Fraction in its implementation, and that it
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000283 uses similar boilerplate code:
284
Christian Heimes3feef612008-02-11 06:19:17 +0000285 4. If B <: Rational, then __radd_ converts both to the
Christian Heimes7b3ce6a2008-01-31 14:31:45 +0000286 builtin rational type (hey look, that's us) and
287 proceeds.
288 5. Otherwise, __radd__ tries to find the nearest common
289 base ABC, and fall back to its builtin type. Since this
290 class doesn't subclass a concrete type, there's no
291 implementation to fall back to, so we need to try as
292 hard as possible to return an actual value, or the user
293 will get a TypeError.
294
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000295 """
296 def forward(a, b):
Christian Heimes3feef612008-02-11 06:19:17 +0000297 if isinstance(b, (int, Fraction)):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000298 return monomorphic_operator(a, b)
299 elif isinstance(b, float):
300 return fallback_operator(float(a), b)
301 elif isinstance(b, complex):
302 return fallback_operator(complex(a), b)
303 else:
304 return NotImplemented
305 forward.__name__ = '__' + fallback_operator.__name__ + '__'
306 forward.__doc__ = monomorphic_operator.__doc__
307
308 def reverse(b, a):
Christian Heimes3feef612008-02-11 06:19:17 +0000309 if isinstance(a, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000310 # Includes ints.
311 return monomorphic_operator(a, b)
312 elif isinstance(a, numbers.Real):
313 return fallback_operator(float(a), float(b))
314 elif isinstance(a, numbers.Complex):
315 return fallback_operator(complex(a), complex(b))
316 else:
317 return NotImplemented
318 reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
319 reverse.__doc__ = monomorphic_operator.__doc__
320
321 return forward, reverse
322
323 def _add(a, b):
324 """a + b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000325 return Fraction(a.numerator * b.denominator +
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000326 b.numerator * a.denominator,
327 a.denominator * b.denominator)
328
329 __add__, __radd__ = _operator_fallbacks(_add, operator.add)
330
331 def _sub(a, b):
332 """a - b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000333 return Fraction(a.numerator * b.denominator -
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000334 b.numerator * a.denominator,
335 a.denominator * b.denominator)
336
337 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub)
338
339 def _mul(a, b):
340 """a * b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000341 return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000342
343 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
344
345 def _div(a, b):
346 """a / b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000347 return Fraction(a.numerator * b.denominator,
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000348 a.denominator * b.numerator)
349
350 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000351
352 def __floordiv__(a, b):
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
356 def __rfloordiv__(b, a):
357 """a // b"""
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000358 return math.floor(a / b)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000359
Christian Heimes969fe572008-01-25 11:23:10 +0000360 def __mod__(a, b):
361 """a % b"""
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000362 div = a // b
363 return a - b * div
364
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000365 def __rmod__(b, a):
366 """a % b"""
Christian Heimes969fe572008-01-25 11:23:10 +0000367 div = a // b
368 return a - b * div
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000369
370 def __pow__(a, b):
371 """a ** b
372
373 If b is not an integer, the result will be a float or complex
374 since roots are generally irrational. If b is an integer, the
375 result will be rational.
376
377 """
Christian Heimes3feef612008-02-11 06:19:17 +0000378 if isinstance(b, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000379 if b.denominator == 1:
380 power = b.numerator
381 if power >= 0:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000382 return Fraction(a._numerator ** power,
383 a._denominator ** power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000384 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000385 return Fraction(a._denominator ** -power,
386 a._numerator ** -power)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000387 else:
388 # A fractional power will generally produce an
389 # irrational number.
390 return float(a) ** float(b)
391 else:
392 return float(a) ** b
393
394 def __rpow__(b, a):
395 """a ** b"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000396 if b._denominator == 1 and b._numerator >= 0:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000397 # If a is an int, keep it that way if possible.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000398 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000399
Christian Heimes3feef612008-02-11 06:19:17 +0000400 if isinstance(a, numbers.Rational):
401 return Fraction(a.numerator, a.denominator) ** b
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000402
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000403 if b._denominator == 1:
404 return a ** b._numerator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000405
406 return a ** float(b)
407
408 def __pos__(a):
Christian Heimes3feef612008-02-11 06:19:17 +0000409 """+a: Coerces a subclass instance to Fraction"""
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 __neg__(a):
413 """-a"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000414 return Fraction(-a._numerator, a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000415
416 def __abs__(a):
417 """abs(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000418 return Fraction(abs(a._numerator), a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000419
420 def __trunc__(a):
421 """trunc(a)"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000422 if a._numerator < 0:
423 return -(-a._numerator // a._denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000424 else:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000425 return a._numerator // a._denominator
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000426
427 def __floor__(a):
428 """Will be math.floor(a) in 3.0."""
429 return a.numerator // a.denominator
430
431 def __ceil__(a):
432 """Will be math.ceil(a) in 3.0."""
433 # The negations cleverly convince floordiv to return the ceiling.
434 return -(-a.numerator // a.denominator)
435
436 def __round__(self, ndigits=None):
437 """Will be round(self, ndigits) in 3.0.
438
439 Rounds half toward even.
440 """
441 if ndigits is None:
442 floor, remainder = divmod(self.numerator, self.denominator)
443 if remainder * 2 < self.denominator:
444 return floor
445 elif remainder * 2 > self.denominator:
446 return floor + 1
447 # Deal with the half case:
448 elif floor % 2 == 0:
449 return floor
450 else:
451 return floor + 1
452 shift = 10**abs(ndigits)
453 # See _operator_fallbacks.forward to check that the results of
Christian Heimes3feef612008-02-11 06:19:17 +0000454 # these operations will always be Fraction and therefore have
Jeffrey Yasskin9893de12008-01-17 07:36:30 +0000455 # round().
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000456 if ndigits > 0:
Christian Heimes3feef612008-02-11 06:19:17 +0000457 return Fraction(round(self * shift), shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000458 else:
Christian Heimes3feef612008-02-11 06:19:17 +0000459 return Fraction(round(self / shift) * shift)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000460
461 def __hash__(self):
462 """hash(self)
463
464 Tricky because values that are exactly representable as a
465 float must have the same hash as that float.
466
467 """
Christian Heimes969fe572008-01-25 11:23:10 +0000468 # XXX since this method is expensive, consider caching the result
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000469 if self._denominator == 1:
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000470 # Get integers right.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000471 return hash(self._numerator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000472 # Expensive check, but definitely correct.
473 if self == float(self):
474 return hash(float(self))
475 else:
476 # Use tuple's hash to avoid a high collision rate on
477 # simple fractions.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000478 return hash((self._numerator, self._denominator))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000479
480 def __eq__(a, b):
481 """a == b"""
Christian Heimes3feef612008-02-11 06:19:17 +0000482 if isinstance(b, numbers.Rational):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000483 return (a._numerator == b.numerator and
484 a._denominator == b.denominator)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000485 if isinstance(b, numbers.Complex) and b.imag == 0:
486 b = b.real
487 if isinstance(b, float):
488 return a == a.from_float(b)
489 else:
490 # XXX: If b.__eq__ is implemented like this method, it may
491 # give the wrong answer after float(a) changes a's
492 # value. Better ways of doing this are welcome.
493 return float(a) == b
494
495 def _subtractAndCompareToZero(a, b, op):
496 """Helper function for comparison operators.
497
498 Subtracts b from a, exactly if possible, and compares the
499 result with 0 using op, in such a way that the comparison
500 won't recurse. If the difference raises a TypeError, returns
501 NotImplemented instead.
502
503 """
504 if isinstance(b, numbers.Complex) and b.imag == 0:
505 b = b.real
506 if isinstance(b, float):
507 b = a.from_float(b)
508 try:
Christian Heimes3feef612008-02-11 06:19:17 +0000509 # XXX: If b <: Real but not <: Rational, this is likely
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000510 # to fall back to a float. If the actual values differ by
511 # less than MIN_FLOAT, this could falsely call them equal,
512 # which would make <= inconsistent with ==. Better ways of
513 # doing this are welcome.
514 diff = a - b
515 except TypeError:
516 return NotImplemented
Christian Heimes3feef612008-02-11 06:19:17 +0000517 if isinstance(diff, numbers.Rational):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000518 return op(diff.numerator, 0)
519 return op(diff, 0)
520
521 def __lt__(a, b):
522 """a < b"""
523 return a._subtractAndCompareToZero(b, operator.lt)
524
525 def __gt__(a, b):
526 """a > b"""
527 return a._subtractAndCompareToZero(b, operator.gt)
528
529 def __le__(a, b):
530 """a <= b"""
531 return a._subtractAndCompareToZero(b, operator.le)
532
533 def __ge__(a, b):
534 """a >= b"""
535 return a._subtractAndCompareToZero(b, operator.ge)
536
537 def __bool__(a):
538 """a != 0"""
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000539 return a._numerator != 0
Christian Heimes969fe572008-01-25 11:23:10 +0000540
541 # support for pickling, copy, and deepcopy
542
543 def __reduce__(self):
544 return (self.__class__, (str(self),))
545
546 def __copy__(self):
Christian Heimes3feef612008-02-11 06:19:17 +0000547 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000548 return self # I'm immutable; therefore I am my own clone
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000549 return self.__class__(self._numerator, self._denominator)
Christian Heimes969fe572008-01-25 11:23:10 +0000550
551 def __deepcopy__(self, memo):
Christian Heimes3feef612008-02-11 06:19:17 +0000552 if type(self) == Fraction:
Christian Heimes969fe572008-01-25 11:23:10 +0000553 return self # My components are also immutable
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000554 return self.__class__(self._numerator, self._denominator)