11# Originally contributed by Sjoerd Mullender.
22# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
33
4- """Fraction, infinite-precision,real numbers."""
4+ """Fraction, infinite-precision,rational numbers."""
55
66from decimal import Decimal
77import math
1010import re
1111import sys
1212
13- __all__ = ['Fraction' , 'gcd' ]
13+ __all__ = ['Fraction' ]
1414
1515
16-
17- def gcd (a ,b ):
18- """Calculate the Greatest Common Divisor of a and b.
19-
20- Unless b==0, the result will have the same sign as b (so that when
21- b is divided by it, the result comes out positive).
22- """
23- import warnings
24- warnings .warn ('fractions.gcd() is deprecated. Use math.gcd() instead.' ,
25- DeprecationWarning ,2 )
26- if type (a )is int is type (b ):
27- if (b or a )< 0 :
28- return - math .gcd (a ,b )
29- return math .gcd (a ,b )
30- return _gcd (a ,b )
31-
32- def _gcd (a ,b ):
33- # Supports non-integers for backward compatibility.
34- while b :
35- a ,b = b ,a % b
36- return a
37-
3816# Constants related to the hash implementation; hash(x) is based
3917# on the reduction of x modulo the prime _PyHASH_MODULUS.
4018_PyHASH_MODULUS = sys .hash_info .modulus
@@ -43,17 +21,17 @@ def _gcd(a, b):
4321_PyHASH_INF = sys .hash_info .inf
4422
4523_RATIONAL_FORMAT = re .compile (r"""
46- \A\s* # optional whitespace at the start, then
47- (?P<sign>[-+]?) # an optional sign, then
48- (?=\d|\.\d) # lookahead for digit or .digit
49- (?P<num>\d*) # numerator (possibly empty)
50- (?: # followed by
51- (?:/(?P<denom>\d+))? # an optional denominator
52- | # or
53- (?:\.(?P<decimal>\d *))? # an optional fractional part
54- (?:E(?P<exp>[-+]?\d+))? # and optional exponent
24+ \A\s* # optional whitespace at the start,
25+ (?P<sign>[-+]?) # an optional sign, then
26+ (?=\d|\.\d) # lookahead for digit or .digit
27+ (?P<num>\d*|\d+(_\d+)* ) # numerator (possibly empty)
28+ (?: # followed by
29+ (?:/(?P<denom>\d+(_\d+)*))? # an optional denominator
30+ | # or
31+ (?:\.(?P<decimal>d*|\d+(_\d+) *))? # an optional fractional part
32+ (?:E(?P<exp>[-+]?\d+(_\d+)*))? # and optional exponent
5533 )
56- \s*\Z # and optional whitespace to finish
34+ \s*\Z # and optional whitespace to finish
5735""" ,re .VERBOSE | re .IGNORECASE )
5836
5937
@@ -144,6 +122,7 @@ def __new__(cls, numerator=0, denominator=None, *, _normalize=True):
144122denominator = 1
145123decimal = m .group ('decimal' )
146124if decimal :
125+ decimal = decimal .replace ('_' ,'' )
147126scale = 10 ** len (decimal )
148127numerator = numerator * scale + int (decimal )
149128denominator *= scale
@@ -177,13 +156,9 @@ def __new__(cls, numerator=0, denominator=None, *, _normalize=True):
177156if denominator == 0 :
178157raise ZeroDivisionError ('Fraction(%s, 0)' % numerator )
179158if _normalize :
180- if type (numerator )is int is type (denominator ):
181- # *very* normal case
182- g = math .gcd (numerator ,denominator )
183- if denominator < 0 :
184- g = - g
185- else :
186- g = _gcd (numerator ,denominator )
159+ g = math .gcd (numerator ,denominator )
160+ if denominator < 0 :
161+ g = - g
187162numerator //= g
188163denominator //= g
189164self ._numerator = numerator
@@ -406,32 +381,139 @@ def reverse(b, a):
406381
407382return forward ,reverse
408383
384+ # Rational arithmetic algorithms: Knuth, TAOCP, Volume 2, 4.5.1.
385+ #
386+ # Assume input fractions a and b are normalized.
387+ #
388+ # 1) Consider addition/subtraction.
389+ #
390+ # Let g = gcd(da, db). Then
391+ #
392+ # na nb na*db ± nb*da
393+ # a ± b == -- ± -- == ------------- ==
394+ # da db da*db
395+ #
396+ # na*(db//g) ± nb*(da//g) t
397+ # == ----------------------- == -
398+ # (da*db)//g d
399+ #
400+ # Now, if g > 1, we're working with smaller integers.
401+ #
402+ # Note, that t, (da//g) and (db//g) are pairwise coprime.
403+ #
404+ # Indeed, (da//g) and (db//g) share no common factors (they were
405+ # removed) and da is coprime with na (since input fractions are
406+ # normalized), hence (da//g) and na are coprime. By symmetry,
407+ # (db//g) and nb are coprime too. Then,
408+ #
409+ # gcd(t, da//g) == gcd(na*(db//g), da//g) == 1
410+ # gcd(t, db//g) == gcd(nb*(da//g), db//g) == 1
411+ #
412+ # Above allows us optimize reduction of the result to lowest
413+ # terms. Indeed,
414+ #
415+ # g2 = gcd(t, d) == gcd(t, (da//g)*(db//g)*g) == gcd(t, g)
416+ #
417+ # t//g2 t//g2
418+ # a ± b == ----------------------- == ----------------
419+ # (da//g)*(db//g)*(g//g2) (da//g)*(db//g2)
420+ #
421+ # is a normalized fraction. This is useful because the unnormalized
422+ # denominator d could be much larger than g.
423+ #
424+ # We should special-case g == 1 (and g2 == 1), since 60.8% of
425+ # randomly-chosen integers are coprime:
426+ # https://en.wikipedia.org/wiki/Coprime_integers#Probability_of_coprimality
427+ # Note, that g2 == 1 always for fractions, obtained from floats: here
428+ # g is a power of 2 and the unnormalized numerator t is an odd integer.
429+ #
430+ # 2) Consider multiplication
431+ #
432+ # Let g1 = gcd(na, db) and g2 = gcd(nb, da), then
433+ #
434+ # na*nb na*nb (na//g1)*(nb//g2)
435+ # a*b == ----- == ----- == -----------------
436+ # da*db db*da (db//g1)*(da//g2)
437+ #
438+ # Note, that after divisions we're multiplying smaller integers.
439+ #
440+ # Also, the resulting fraction is normalized, because each of
441+ # two factors in the numerator is coprime to each of the two factors
442+ # in the denominator.
443+ #
444+ # Indeed, pick (na//g1). It's coprime with (da//g2), because input
445+ # fractions are normalized. It's also coprime with (db//g1), because
446+ # common factors are removed by g1 == gcd(na, db).
447+ #
448+ # As for addition/subtraction, we should special-case g1 == 1
449+ # and g2 == 1 for same reason. That happens also for multiplying
450+ # rationals, obtained from floats.
451+
409452def _add (a ,b ):
410453"""a + b"""
411- da ,db = a .denominator ,b .denominator
412- return Fraction (a .numerator * db + b .numerator * da ,
413- da * db )
454+ na ,da = a .numerator ,a .denominator
455+ nb ,db = b .numerator ,b .denominator
456+ g = math .gcd (da ,db )
457+ if g == 1 :
458+ return Fraction (na * db + da * nb ,da * db ,_normalize = False )
459+ s = da // g
460+ t = na * (db // g )+ nb * s
461+ g2 = math .gcd (t ,g )
462+ if g2 == 1 :
463+ return Fraction (t ,s * db ,_normalize = False )
464+ return Fraction (t // g2 ,s * (db // g2 ),_normalize = False )
414465
415466__add__ ,__radd__ = _operator_fallbacks (_add ,operator .add )
416467
417468def _sub (a ,b ):
418469"""a - b"""
419- da ,db = a .denominator ,b .denominator
420- return Fraction (a .numerator * db - b .numerator * da ,
421- da * db )
470+ na ,da = a .numerator ,a .denominator
471+ nb ,db = b .numerator ,b .denominator
472+ g = math .gcd (da ,db )
473+ if g == 1 :
474+ return Fraction (na * db - da * nb ,da * db ,_normalize = False )
475+ s = da // g
476+ t = na * (db // g )- nb * s
477+ g2 = math .gcd (t ,g )
478+ if g2 == 1 :
479+ return Fraction (t ,s * db ,_normalize = False )
480+ return Fraction (t // g2 ,s * (db // g2 ),_normalize = False )
422481
423482__sub__ ,__rsub__ = _operator_fallbacks (_sub ,operator .sub )
424483
425484def _mul (a ,b ):
426485"""a * b"""
427- return Fraction (a .numerator * b .numerator ,a .denominator * b .denominator )
486+ na ,da = a .numerator ,a .denominator
487+ nb ,db = b .numerator ,b .denominator
488+ g1 = math .gcd (na ,db )
489+ if g1 > 1 :
490+ na //= g1
491+ db //= g1
492+ g2 = math .gcd (nb ,da )
493+ if g2 > 1 :
494+ nb //= g2
495+ da //= g2
496+ return Fraction (na * nb ,db * da ,_normalize = False )
428497
429498__mul__ ,__rmul__ = _operator_fallbacks (_mul ,operator .mul )
430499
431500def _div (a ,b ):
432501"""a / b"""
433- return Fraction (a .numerator * b .denominator ,
434- a .denominator * b .numerator )
502+ # Same as _mul(), with inversed b.
503+ na ,da = a .numerator ,a .denominator
504+ nb ,db = b .numerator ,b .denominator
505+ g1 = math .gcd (na ,nb )
506+ if g1 > 1 :
507+ na //= g1
508+ nb //= g1
509+ g2 = math .gcd (db ,da )
510+ if g2 > 1 :
511+ da //= g2
512+ db //= g2
513+ n ,d = na * db ,nb * da
514+ if d < 0 :
515+ n ,d = - n ,- d
516+ return Fraction (n ,d ,_normalize = False )
435517
436518__truediv__ ,__rtruediv__ = _operator_fallbacks (_div ,operator .truediv )
437519
@@ -512,8 +594,15 @@ def __abs__(a):
512594"""abs(a)"""
513595return Fraction (abs (a ._numerator ),a ._denominator ,_normalize = False )
514596
597+ def __int__ (a ,_index = operator .index ):
598+ """int(a)"""
599+ if a ._numerator < 0 :
600+ return _index (- (- a ._numerator // a ._denominator ))
601+ else :
602+ return _index (a ._numerator // a ._denominator )
603+
515604def __trunc__ (a ):
516- """trunc(a)"""
605+ """math. trunc(a)"""
517606if a ._numerator < 0 :
518607return - (- a ._numerator // a ._denominator )
519608else :
@@ -556,23 +645,34 @@ def __round__(self, ndigits=None):
556645def __hash__ (self ):
557646"""hash(self)"""
558647
559- # XXX since this method is expensive, consider caching the result
560-
561- # In order to make sure that the hash of a Fraction agrees
562- # with the hash of a numerically equal integer, float or
563- # Decimal instance, we follow the rules for numeric hashes
564- # outlined in the documentation. (See library docs, 'Built-in
565- # Types').
648+ # To make sure that the hash of a Fraction agrees with the hash
649+ # of a numerically equal integer, float or Decimal instance, we
650+ # follow the rules for numeric hashes outlined in the
651+ # documentation. (See library docs, 'Built-in Types').
566652
567- # dinv is the inverse of self._denominator modulo the prime
568- # _PyHASH_MODULUS, or 0 if self._denominator is divisible by
569- # _PyHASH_MODULUS.
570- dinv = pow (self ._denominator ,_PyHASH_MODULUS - 2 ,_PyHASH_MODULUS )
571- if not dinv :
653+ try :
654+ dinv = pow (self ._denominator ,- 1 ,_PyHASH_MODULUS )
655+ except ValueError :
656+ # ValueError means there is no modular inverse.
572657hash_ = _PyHASH_INF
573658else :
574- hash_ = abs (self ._numerator )* dinv % _PyHASH_MODULUS
575- result = hash_ if self >= 0 else - hash_
659+ # The general algorithm now specifies that the absolute value of
660+ # the hash is
661+ # (|N| * dinv) % P
662+ # where N is self._numerator and P is _PyHASH_MODULUS. That's
663+ # optimized here in two ways: first, for a non-negative int i,
664+ # hash(i) == i % P, but the int hash implementation doesn't need
665+ # to divide, and is faster than doing % P explicitly. So we do
666+ # hash(|N| * dinv)
667+ # instead. Second, N is unbounded, so its product with dinv may
668+ # be arbitrarily expensive to compute. The final answer is the
669+ # same if we use the bounded |N| % P instead, which can again
670+ # be done with an int hash() call. If 0 <= i < P, hash(i) == i,
671+ # so this nested hash() call wastes a bit of time making a
672+ # redundant copy when |N| < P, but can save an arbitrarily large
673+ # amount of computation for large |N|.
674+ hash_ = hash (hash (abs (self ._numerator ))* dinv )
675+ result = hash_ if self ._numerator >= 0 else - hash_
576676return - 2 if result == - 1 else result
577677
578678def __eq__ (a ,b ):
@@ -643,7 +743,7 @@ def __bool__(a):
643743# support for pickling, copy, and deepcopy
644744
645745def __reduce__ (self ):
646- return (self .__class__ , (str ( self ), ))
746+ return (self .__class__ , (self . _numerator , self . _denominator ))
647747
648748def __copy__ (self ):
649749if type (self )== Fraction :