• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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