1# Originally contributed by Sjoerd Mullender. 2# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>. 3 4"""Fraction, infinite-precision, real numbers.""" 5 6from decimal import Decimal 7import math 8import numbers 9import operator 10import re 11import sys 12 13__all__ = ['Fraction'] 14 15 16# Constants related to the hash implementation; hash(x) is based 17# on the reduction of x modulo the prime _PyHASH_MODULUS. 18_PyHASH_MODULUS = sys.hash_info.modulus 19# Value to be used for rationals that reduce to infinity modulo 20# _PyHASH_MODULUS. 21_PyHASH_INF = sys.hash_info.inf 22 23_RATIONAL_FORMAT = re.compile(r""" 24 \A\s* # optional whitespace at the start, then 25 (?P<sign>[-+]?) # an optional sign, then 26 (?=\d|\.\d) # lookahead for digit or .digit 27 (?P<num>\d*) # numerator (possibly empty) 28 (?: # followed by 29 (?:/(?P<denom>\d+))? # an optional denominator 30 | # or 31 (?:\.(?P<decimal>\d*))? # an optional fractional part 32 (?:E(?P<exp>[-+]?\d+))? # and optional exponent 33 ) 34 \s*\Z # and optional whitespace to finish 35""", re.VERBOSE | re.IGNORECASE) 36 37 38class Fraction(numbers.Rational): 39 """This class implements rational numbers. 40 41 In the two-argument form of the constructor, Fraction(8, 6) will 42 produce a rational number equivalent to 4/3. Both arguments must 43 be Rational. The numerator defaults to 0 and the denominator 44 defaults to 1 so that Fraction(3) == 3 and Fraction() == 0. 45 46 Fractions can also be constructed from: 47 48 - numeric strings similar to those accepted by the 49 float constructor (for example, '-2.3' or '1e10') 50 51 - strings of the form '123/456' 52 53 - float and Decimal instances 54 55 - other Rational instances (including integers) 56 57 """ 58 59 __slots__ = ('_numerator', '_denominator') 60 61 # We're immutable, so use __new__ not __init__ 62 def __new__(cls, numerator=0, denominator=None, *, _normalize=True): 63 """Constructs a Rational. 64 65 Takes a string like '3/2' or '1.5', another Rational instance, a 66 numerator/denominator pair, or a float. 67 68 Examples 69 -------- 70 71 >>> Fraction(10, -8) 72 Fraction(-5, 4) 73 >>> Fraction(Fraction(1, 7), 5) 74 Fraction(1, 35) 75 >>> Fraction(Fraction(1, 7), Fraction(2, 3)) 76 Fraction(3, 14) 77 >>> Fraction('314') 78 Fraction(314, 1) 79 >>> Fraction('-35/4') 80 Fraction(-35, 4) 81 >>> Fraction('3.1415') # conversion from numeric string 82 Fraction(6283, 2000) 83 >>> Fraction('-47e-2') # string may include a decimal exponent 84 Fraction(-47, 100) 85 >>> Fraction(1.47) # direct construction from float (exact conversion) 86 Fraction(6620291452234629, 4503599627370496) 87 >>> Fraction(2.25) 88 Fraction(9, 4) 89 >>> Fraction(Decimal('1.47')) 90 Fraction(147, 100) 91 92 """ 93 self = super(Fraction, cls).__new__(cls) 94 95 if denominator is None: 96 if type(numerator) is int: 97 self._numerator = numerator 98 self._denominator = 1 99 return self 100 101 elif isinstance(numerator, numbers.Rational): 102 self._numerator = numerator.numerator 103 self._denominator = numerator.denominator 104 return self 105 106 elif isinstance(numerator, (float, Decimal)): 107 # Exact conversion 108 self._numerator, self._denominator = numerator.as_integer_ratio() 109 return self 110 111 elif isinstance(numerator, str): 112 # Handle construction from strings. 113 m = _RATIONAL_FORMAT.match(numerator) 114 if m is None: 115 raise ValueError('Invalid literal for Fraction: %r' % 116 numerator) 117 numerator = int(m.group('num') or '0') 118 denom = m.group('denom') 119 if denom: 120 denominator = int(denom) 121 else: 122 denominator = 1 123 decimal = m.group('decimal') 124 if decimal: 125 scale = 10**len(decimal) 126 numerator = numerator * scale + int(decimal) 127 denominator *= scale 128 exp = m.group('exp') 129 if exp: 130 exp = int(exp) 131 if exp >= 0: 132 numerator *= 10**exp 133 else: 134 denominator *= 10**-exp 135 if m.group('sign') == '-': 136 numerator = -numerator 137 138 else: 139 raise TypeError("argument should be a string " 140 "or a Rational instance") 141 142 elif type(numerator) is int is type(denominator): 143 pass # *very* normal case 144 145 elif (isinstance(numerator, numbers.Rational) and 146 isinstance(denominator, numbers.Rational)): 147 numerator, denominator = ( 148 numerator.numerator * denominator.denominator, 149 denominator.numerator * numerator.denominator 150 ) 151 else: 152 raise TypeError("both arguments should be " 153 "Rational instances") 154 155 if denominator == 0: 156 raise ZeroDivisionError('Fraction(%s, 0)' % numerator) 157 if _normalize: 158 g = math.gcd(numerator, denominator) 159 if denominator < 0: 160 g = -g 161 numerator //= g 162 denominator //= g 163 self._numerator = numerator 164 self._denominator = denominator 165 return self 166 167 @classmethod 168 def from_float(cls, f): 169 """Converts a finite float to a rational number, exactly. 170 171 Beware that Fraction.from_float(0.3) != Fraction(3, 10). 172 173 """ 174 if isinstance(f, numbers.Integral): 175 return cls(f) 176 elif not isinstance(f, float): 177 raise TypeError("%s.from_float() only takes floats, not %r (%s)" % 178 (cls.__name__, f, type(f).__name__)) 179 return cls(*f.as_integer_ratio()) 180 181 @classmethod 182 def from_decimal(cls, dec): 183 """Converts a finite Decimal instance to a rational number, exactly.""" 184 from decimal import Decimal 185 if isinstance(dec, numbers.Integral): 186 dec = Decimal(int(dec)) 187 elif not isinstance(dec, Decimal): 188 raise TypeError( 189 "%s.from_decimal() only takes Decimals, not %r (%s)" % 190 (cls.__name__, dec, type(dec).__name__)) 191 return cls(*dec.as_integer_ratio()) 192 193 def as_integer_ratio(self): 194 """Return the integer ratio as a tuple. 195 196 Return a tuple of two integers, whose ratio is equal to the 197 Fraction and with a positive denominator. 198 """ 199 return (self._numerator, self._denominator) 200 201 def limit_denominator(self, max_denominator=1000000): 202 """Closest Fraction to self with denominator at most max_denominator. 203 204 >>> Fraction('3.141592653589793').limit_denominator(10) 205 Fraction(22, 7) 206 >>> Fraction('3.141592653589793').limit_denominator(100) 207 Fraction(311, 99) 208 >>> Fraction(4321, 8765).limit_denominator(10000) 209 Fraction(4321, 8765) 210 211 """ 212 # Algorithm notes: For any real number x, define a *best upper 213 # approximation* to x to be a rational number p/q such that: 214 # 215 # (1) p/q >= x, and 216 # (2) if p/q > r/s >= x then s > q, for any rational r/s. 217 # 218 # Define *best lower approximation* similarly. Then it can be 219 # proved that a rational number is a best upper or lower 220 # approximation to x if, and only if, it is a convergent or 221 # semiconvergent of the (unique shortest) continued fraction 222 # associated to x. 223 # 224 # To find a best rational approximation with denominator <= M, 225 # we find the best upper and lower approximations with 226 # denominator <= M and take whichever of these is closer to x. 227 # In the event of a tie, the bound with smaller denominator is 228 # chosen. If both denominators are equal (which can happen 229 # only when max_denominator == 1 and self is midway between 230 # two integers) the lower bound---i.e., the floor of self, is 231 # taken. 232 233 if max_denominator < 1: 234 raise ValueError("max_denominator should be at least 1") 235 if self._denominator <= max_denominator: 236 return Fraction(self) 237 238 p0, q0, p1, q1 = 0, 1, 1, 0 239 n, d = self._numerator, self._denominator 240 while True: 241 a = n//d 242 q2 = q0+a*q1 243 if q2 > max_denominator: 244 break 245 p0, q0, p1, q1 = p1, q1, p0+a*p1, q2 246 n, d = d, n-a*d 247 248 k = (max_denominator-q0)//q1 249 bound1 = Fraction(p0+k*p1, q0+k*q1) 250 bound2 = Fraction(p1, q1) 251 if abs(bound2 - self) <= abs(bound1-self): 252 return bound2 253 else: 254 return bound1 255 256 @property 257 def numerator(a): 258 return a._numerator 259 260 @property 261 def denominator(a): 262 return a._denominator 263 264 def __repr__(self): 265 """repr(self)""" 266 return '%s(%s, %s)' % (self.__class__.__name__, 267 self._numerator, self._denominator) 268 269 def __str__(self): 270 """str(self)""" 271 if self._denominator == 1: 272 return str(self._numerator) 273 else: 274 return '%s/%s' % (self._numerator, self._denominator) 275 276 def _operator_fallbacks(monomorphic_operator, fallback_operator): 277 """Generates forward and reverse operators given a purely-rational 278 operator and a function from the operator module. 279 280 Use this like: 281 __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op) 282 283 In general, we want to implement the arithmetic operations so 284 that mixed-mode operations either call an implementation whose 285 author knew about the types of both arguments, or convert both 286 to the nearest built in type and do the operation there. In 287 Fraction, that means that we define __add__ and __radd__ as: 288 289 def __add__(self, other): 290 # Both types have numerators/denominator attributes, 291 # so do the operation directly 292 if isinstance(other, (int, Fraction)): 293 return Fraction(self.numerator * other.denominator + 294 other.numerator * self.denominator, 295 self.denominator * other.denominator) 296 # float and complex don't have those operations, but we 297 # know about those types, so special case them. 298 elif isinstance(other, float): 299 return float(self) + other 300 elif isinstance(other, complex): 301 return complex(self) + other 302 # Let the other type take over. 303 return NotImplemented 304 305 def __radd__(self, other): 306 # radd handles more types than add because there's 307 # nothing left to fall back to. 308 if isinstance(other, numbers.Rational): 309 return Fraction(self.numerator * other.denominator + 310 other.numerator * self.denominator, 311 self.denominator * other.denominator) 312 elif isinstance(other, Real): 313 return float(other) + float(self) 314 elif isinstance(other, Complex): 315 return complex(other) + complex(self) 316 return NotImplemented 317 318 319 There are 5 different cases for a mixed-type addition on 320 Fraction. I'll refer to all of the above code that doesn't 321 refer to Fraction, float, or complex as "boilerplate". 'r' 322 will be an instance of Fraction, which is a subtype of 323 Rational (r : Fraction <: Rational), and b : B <: 324 Complex. The first three involve 'r + b': 325 326 1. If B <: Fraction, int, float, or complex, we handle 327 that specially, and all is well. 328 2. If Fraction falls back to the boilerplate code, and it 329 were to return a value from __add__, we'd miss the 330 possibility that B defines a more intelligent __radd__, 331 so the boilerplate should return NotImplemented from 332 __add__. In particular, we don't handle Rational 333 here, even though we could get an exact answer, in case 334 the other type wants to do something special. 335 3. If B <: Fraction, Python tries B.__radd__ before 336 Fraction.__add__. This is ok, because it was 337 implemented with knowledge of Fraction, so it can 338 handle those instances before delegating to Real or 339 Complex. 340 341 The next two situations describe 'b + r'. We assume that b 342 didn't know about Fraction in its implementation, and that it 343 uses similar boilerplate code: 344 345 4. If B <: Rational, then __radd_ converts both to the 346 builtin rational type (hey look, that's us) and 347 proceeds. 348 5. Otherwise, __radd__ tries to find the nearest common 349 base ABC, and fall back to its builtin type. Since this 350 class doesn't subclass a concrete type, there's no 351 implementation to fall back to, so we need to try as 352 hard as possible to return an actual value, or the user 353 will get a TypeError. 354 355 """ 356 def forward(a, b): 357 if isinstance(b, (int, Fraction)): 358 return monomorphic_operator(a, b) 359 elif isinstance(b, float): 360 return fallback_operator(float(a), b) 361 elif isinstance(b, complex): 362 return fallback_operator(complex(a), b) 363 else: 364 return NotImplemented 365 forward.__name__ = '__' + fallback_operator.__name__ + '__' 366 forward.__doc__ = monomorphic_operator.__doc__ 367 368 def reverse(b, a): 369 if isinstance(a, numbers.Rational): 370 # Includes ints. 371 return monomorphic_operator(a, b) 372 elif isinstance(a, numbers.Real): 373 return fallback_operator(float(a), float(b)) 374 elif isinstance(a, numbers.Complex): 375 return fallback_operator(complex(a), complex(b)) 376 else: 377 return NotImplemented 378 reverse.__name__ = '__r' + fallback_operator.__name__ + '__' 379 reverse.__doc__ = monomorphic_operator.__doc__ 380 381 return forward, reverse 382 383 # Rational arithmetic algorithms: Knuth, TAOCP, Volume 2, 4.5.1. 384 # 385 # Assume input fractions a and b are normalized. 386 # 387 # 1) Consider addition/subtraction. 388 # 389 # Let g = gcd(da, db). Then 390 # 391 # na nb na*db ± nb*da 392 # a ± b == -- ± -- == ------------- == 393 # da db da*db 394 # 395 # na*(db//g) ± nb*(da//g) t 396 # == ----------------------- == - 397 # (da*db)//g d 398 # 399 # Now, if g > 1, we're working with smaller integers. 400 # 401 # Note, that t, (da//g) and (db//g) are pairwise coprime. 402 # 403 # Indeed, (da//g) and (db//g) share no common factors (they were 404 # removed) and da is coprime with na (since input fractions are 405 # normalized), hence (da//g) and na are coprime. By symmetry, 406 # (db//g) and nb are coprime too. Then, 407 # 408 # gcd(t, da//g) == gcd(na*(db//g), da//g) == 1 409 # gcd(t, db//g) == gcd(nb*(da//g), db//g) == 1 410 # 411 # Above allows us optimize reduction of the result to lowest 412 # terms. Indeed, 413 # 414 # g2 = gcd(t, d) == gcd(t, (da//g)*(db//g)*g) == gcd(t, g) 415 # 416 # t//g2 t//g2 417 # a ± b == ----------------------- == ---------------- 418 # (da//g)*(db//g)*(g//g2) (da//g)*(db//g2) 419 # 420 # is a normalized fraction. This is useful because the unnormalized 421 # denominator d could be much larger than g. 422 # 423 # We should special-case g == 1 (and g2 == 1), since 60.8% of 424 # randomly-chosen integers are coprime: 425 # https://en.wikipedia.org/wiki/Coprime_integers#Probability_of_coprimality 426 # Note, that g2 == 1 always for fractions, obtained from floats: here 427 # g is a power of 2 and the unnormalized numerator t is an odd integer. 428 # 429 # 2) Consider multiplication 430 # 431 # Let g1 = gcd(na, db) and g2 = gcd(nb, da), then 432 # 433 # na*nb na*nb (na//g1)*(nb//g2) 434 # a*b == ----- == ----- == ----------------- 435 # da*db db*da (db//g1)*(da//g2) 436 # 437 # Note, that after divisions we're multiplying smaller integers. 438 # 439 # Also, the resulting fraction is normalized, because each of 440 # two factors in the numerator is coprime to each of the two factors 441 # in the denominator. 442 # 443 # Indeed, pick (na//g1). It's coprime with (da//g2), because input 444 # fractions are normalized. It's also coprime with (db//g1), because 445 # common factors are removed by g1 == gcd(na, db). 446 # 447 # As for addition/subtraction, we should special-case g1 == 1 448 # and g2 == 1 for same reason. That happens also for multiplying 449 # rationals, obtained from floats. 450 451 def _add(a, b): 452 """a + b""" 453 na, da = a.numerator, a.denominator 454 nb, db = b.numerator, b.denominator 455 g = math.gcd(da, db) 456 if g == 1: 457 return Fraction(na * db + da * nb, da * db, _normalize=False) 458 s = da // g 459 t = na * (db // g) + nb * s 460 g2 = math.gcd(t, g) 461 if g2 == 1: 462 return Fraction(t, s * db, _normalize=False) 463 return Fraction(t // g2, s * (db // g2), _normalize=False) 464 465 __add__, __radd__ = _operator_fallbacks(_add, operator.add) 466 467 def _sub(a, b): 468 """a - b""" 469 na, da = a.numerator, a.denominator 470 nb, db = b.numerator, b.denominator 471 g = math.gcd(da, db) 472 if g == 1: 473 return Fraction(na * db - da * nb, da * db, _normalize=False) 474 s = da // g 475 t = na * (db // g) - nb * s 476 g2 = math.gcd(t, g) 477 if g2 == 1: 478 return Fraction(t, s * db, _normalize=False) 479 return Fraction(t // g2, s * (db // g2), _normalize=False) 480 481 __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) 482 483 def _mul(a, b): 484 """a * b""" 485 na, da = a.numerator, a.denominator 486 nb, db = b.numerator, b.denominator 487 g1 = math.gcd(na, db) 488 if g1 > 1: 489 na //= g1 490 db //= g1 491 g2 = math.gcd(nb, da) 492 if g2 > 1: 493 nb //= g2 494 da //= g2 495 return Fraction(na * nb, db * da, _normalize=False) 496 497 __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul) 498 499 def _div(a, b): 500 """a / b""" 501 # Same as _mul(), with inversed b. 502 na, da = a.numerator, a.denominator 503 nb, db = b.numerator, b.denominator 504 g1 = math.gcd(na, nb) 505 if g1 > 1: 506 na //= g1 507 nb //= g1 508 g2 = math.gcd(db, da) 509 if g2 > 1: 510 da //= g2 511 db //= g2 512 n, d = na * db, nb * da 513 if d < 0: 514 n, d = -n, -d 515 return Fraction(n, d, _normalize=False) 516 517 __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv) 518 519 def _floordiv(a, b): 520 """a // b""" 521 return (a.numerator * b.denominator) // (a.denominator * b.numerator) 522 523 __floordiv__, __rfloordiv__ = _operator_fallbacks(_floordiv, operator.floordiv) 524 525 def _divmod(a, b): 526 """(a // b, a % b)""" 527 da, db = a.denominator, b.denominator 528 div, n_mod = divmod(a.numerator * db, da * b.numerator) 529 return div, Fraction(n_mod, da * db) 530 531 __divmod__, __rdivmod__ = _operator_fallbacks(_divmod, divmod) 532 533 def _mod(a, b): 534 """a % b""" 535 da, db = a.denominator, b.denominator 536 return Fraction((a.numerator * db) % (b.numerator * da), da * db) 537 538 __mod__, __rmod__ = _operator_fallbacks(_mod, operator.mod) 539 540 def __pow__(a, b): 541 """a ** b 542 543 If b is not an integer, the result will be a float or complex 544 since roots are generally irrational. If b is an integer, the 545 result will be rational. 546 547 """ 548 if isinstance(b, numbers.Rational): 549 if b.denominator == 1: 550 power = b.numerator 551 if power >= 0: 552 return Fraction(a._numerator ** power, 553 a._denominator ** power, 554 _normalize=False) 555 elif a._numerator >= 0: 556 return Fraction(a._denominator ** -power, 557 a._numerator ** -power, 558 _normalize=False) 559 else: 560 return Fraction((-a._denominator) ** -power, 561 (-a._numerator) ** -power, 562 _normalize=False) 563 else: 564 # A fractional power will generally produce an 565 # irrational number. 566 return float(a) ** float(b) 567 else: 568 return float(a) ** b 569 570 def __rpow__(b, a): 571 """a ** b""" 572 if b._denominator == 1 and b._numerator >= 0: 573 # If a is an int, keep it that way if possible. 574 return a ** b._numerator 575 576 if isinstance(a, numbers.Rational): 577 return Fraction(a.numerator, a.denominator) ** b 578 579 if b._denominator == 1: 580 return a ** b._numerator 581 582 return a ** float(b) 583 584 def __pos__(a): 585 """+a: Coerces a subclass instance to Fraction""" 586 return Fraction(a._numerator, a._denominator, _normalize=False) 587 588 def __neg__(a): 589 """-a""" 590 return Fraction(-a._numerator, a._denominator, _normalize=False) 591 592 def __abs__(a): 593 """abs(a)""" 594 return Fraction(abs(a._numerator), a._denominator, _normalize=False) 595 596 def __trunc__(a): 597 """trunc(a)""" 598 if a._numerator < 0: 599 return -(-a._numerator // a._denominator) 600 else: 601 return a._numerator // a._denominator 602 603 def __floor__(a): 604 """math.floor(a)""" 605 return a.numerator // a.denominator 606 607 def __ceil__(a): 608 """math.ceil(a)""" 609 # The negations cleverly convince floordiv to return the ceiling. 610 return -(-a.numerator // a.denominator) 611 612 def __round__(self, ndigits=None): 613 """round(self, ndigits) 614 615 Rounds half toward even. 616 """ 617 if ndigits is None: 618 floor, remainder = divmod(self.numerator, self.denominator) 619 if remainder * 2 < self.denominator: 620 return floor 621 elif remainder * 2 > self.denominator: 622 return floor + 1 623 # Deal with the half case: 624 elif floor % 2 == 0: 625 return floor 626 else: 627 return floor + 1 628 shift = 10**abs(ndigits) 629 # See _operator_fallbacks.forward to check that the results of 630 # these operations will always be Fraction and therefore have 631 # round(). 632 if ndigits > 0: 633 return Fraction(round(self * shift), shift) 634 else: 635 return Fraction(round(self / shift) * shift) 636 637 def __hash__(self): 638 """hash(self)""" 639 640 # To make sure that the hash of a Fraction agrees with the hash 641 # of a numerically equal integer, float or Decimal instance, we 642 # follow the rules for numeric hashes outlined in the 643 # documentation. (See library docs, 'Built-in Types'). 644 645 try: 646 dinv = pow(self._denominator, -1, _PyHASH_MODULUS) 647 except ValueError: 648 # ValueError means there is no modular inverse. 649 hash_ = _PyHASH_INF 650 else: 651 # The general algorithm now specifies that the absolute value of 652 # the hash is 653 # (|N| * dinv) % P 654 # where N is self._numerator and P is _PyHASH_MODULUS. That's 655 # optimized here in two ways: first, for a non-negative int i, 656 # hash(i) == i % P, but the int hash implementation doesn't need 657 # to divide, and is faster than doing % P explicitly. So we do 658 # hash(|N| * dinv) 659 # instead. Second, N is unbounded, so its product with dinv may 660 # be arbitrarily expensive to compute. The final answer is the 661 # same if we use the bounded |N| % P instead, which can again 662 # be done with an int hash() call. If 0 <= i < P, hash(i) == i, 663 # so this nested hash() call wastes a bit of time making a 664 # redundant copy when |N| < P, but can save an arbitrarily large 665 # amount of computation for large |N|. 666 hash_ = hash(hash(abs(self._numerator)) * dinv) 667 result = hash_ if self._numerator >= 0 else -hash_ 668 return -2 if result == -1 else result 669 670 def __eq__(a, b): 671 """a == b""" 672 if type(b) is int: 673 return a._numerator == b and a._denominator == 1 674 if isinstance(b, numbers.Rational): 675 return (a._numerator == b.numerator and 676 a._denominator == b.denominator) 677 if isinstance(b, numbers.Complex) and b.imag == 0: 678 b = b.real 679 if isinstance(b, float): 680 if math.isnan(b) or math.isinf(b): 681 # comparisons with an infinity or nan should behave in 682 # the same way for any finite a, so treat a as zero. 683 return 0.0 == b 684 else: 685 return a == a.from_float(b) 686 else: 687 # Since a doesn't know how to compare with b, let's give b 688 # a chance to compare itself with a. 689 return NotImplemented 690 691 def _richcmp(self, other, op): 692 """Helper for comparison operators, for internal use only. 693 694 Implement comparison between a Rational instance `self`, and 695 either another Rational instance or a float `other`. If 696 `other` is not a Rational instance or a float, return 697 NotImplemented. `op` should be one of the six standard 698 comparison operators. 699 700 """ 701 # convert other to a Rational instance where reasonable. 702 if isinstance(other, numbers.Rational): 703 return op(self._numerator * other.denominator, 704 self._denominator * other.numerator) 705 if isinstance(other, float): 706 if math.isnan(other) or math.isinf(other): 707 return op(0.0, other) 708 else: 709 return op(self, self.from_float(other)) 710 else: 711 return NotImplemented 712 713 def __lt__(a, b): 714 """a < b""" 715 return a._richcmp(b, operator.lt) 716 717 def __gt__(a, b): 718 """a > b""" 719 return a._richcmp(b, operator.gt) 720 721 def __le__(a, b): 722 """a <= b""" 723 return a._richcmp(b, operator.le) 724 725 def __ge__(a, b): 726 """a >= b""" 727 return a._richcmp(b, operator.ge) 728 729 def __bool__(a): 730 """a != 0""" 731 # bpo-39274: Use bool() because (a._numerator != 0) can return an 732 # object which is not a bool. 733 return bool(a._numerator) 734 735 # support for pickling, copy, and deepcopy 736 737 def __reduce__(self): 738 return (self.__class__, (str(self),)) 739 740 def __copy__(self): 741 if type(self) == Fraction: 742 return self # I'm immutable; therefore I am my own clone 743 return self.__class__(self._numerator, self._denominator) 744 745 def __deepcopy__(self, memo): 746 if type(self) == Fraction: 747 return self # My components are also immutable 748 return self.__class__(self._numerator, self._denominator) 749