fractions.py revision d058cd2cc8e2a3f61609b92a8fc821ea8ec524ca
1d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin# Originally contributed by Sjoerd Mullender. 2d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>. 3d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin"""Rational, infinite-precision, real numbers.""" 5d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 6d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinfrom __future__ import division 7d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport math 8d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport numbers 9d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport operator 1045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskinimport re 11d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 12d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson__all__ = ["Fraction"] 13d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 14d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark DickinsonRational = numbers.Rational 15d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 16d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 173e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskindef gcd(a, b): 183e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin """Calculate the Greatest Common Divisor of a and b. 19d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 20d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Unless b==0, the result will have the same sign as b (so that when 21d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b is divided by it, the result comes out positive). 22d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 23d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin while b: 24d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a, b = b, a%b 25d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a 26d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 27d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 281dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson_RATIONAL_FORMAT = re.compile(r""" 291dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson \A\s* # optional whitespace at the start, then 301dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson (?P<sign>[-+]?) # an optional sign, then 311dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson (?=\d|\.\d) # lookahead for digit or .digit 321dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson (?P<num>\d*) # numerator (possibly empty) 331dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson (?: # followed by an optional 341dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson /(?P<denom>\d+) # / and denominator 351dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson | # or 361dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson \.(?P<decimal>\d*) # decimal point and fractional part 371dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson )? 381dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson \s*\Z # and optional whitespace to finish 391dabdb25f83d55737c2154b63bc463240fd7bc03Mark Dickinson""", re.VERBOSE) 4045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 4145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 42d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinsonclass Fraction(Rational): 43d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """This class implements rational numbers. 44d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 45d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fraction(8, 6) will produce a rational number equivalent to 46d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4/3. Both arguments must be Integral. The numerator defaults to 0 47d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson and the denominator defaults to 1 so that Fraction(3) == 3 and 48d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fraction() == 0. 49d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 50d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fractions can also be constructed from strings of the form 513e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces. 5245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 53d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 54d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 55dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin __slots__ = ('_numerator', '_denominator') 56d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 5745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # We're immutable, so use __new__ not __init__ 5845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin def __new__(cls, numerator=0, denominator=1): 59d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson """Constructs a Fraction. 6045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 61d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Takes a string like '3/2' or '1.5', another Fraction, or a 623e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator/denominator pair. 6345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 6445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """ 65d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson self = super(Fraction, cls).__new__(cls) 6645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 6745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if denominator == 1: 6845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if isinstance(numerator, basestring): 6945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Handle construction from strings. 7045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin input = numerator 7145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin m = _RATIONAL_FORMAT.match(input) 7245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if m is None: 73d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise ValueError('Invalid literal for Fraction: ' + input) 743e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = m.group('num') 753e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin decimal = m.group('decimal') 763e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin if decimal: 773e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # The literal is a decimal number. 783e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = int(numerator + decimal) 793e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin denominator = 10**len(decimal) 803e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin else: 813e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # The literal is an integer or fraction. 823e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = int(numerator) 833e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # Default denominator to 1. 843e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin denominator = int(m.group('denom') or 1) 853e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin 8645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if m.group('sign') == '-': 8745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin numerator = -numerator 8845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 8945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin elif (not isinstance(numerator, numbers.Integral) and 90d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson isinstance(numerator, Rational)): 9145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Handle copies from other rationals. 9245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin other_rational = numerator 9345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin numerator = other_rational.numerator 9445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin denominator = other_rational.denominator 95d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 96d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if (not isinstance(numerator, numbers.Integral) or 97d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin not isinstance(denominator, numbers.Integral)): 98d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise TypeError("Fraction(%(numerator)s, %(denominator)s):" 99d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin " Both arguments must be integral." % locals()) 100d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 101d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if denominator == 0: 102d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise ZeroDivisionError('Fraction(%s, 0)' % numerator) 103d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 1043e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin g = gcd(numerator, denominator) 105dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin self._numerator = int(numerator // g) 106dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin self._denominator = int(denominator // g) 10745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return self 108d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 10974d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson @staticmethod 11074d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson def from_float(f): 11145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """Converts a finite float to a rational number, exactly. 11245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 113d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Beware that Fraction.from_float(0.3) != Fraction(3, 10). 11445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 11545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """ 116d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if not isinstance(f, float): 117d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise TypeError("Fraction.from_float() only takes floats, " 11874d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson "not %r (%s)" % (f, type(f).__name__)) 119d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if math.isnan(f) or math.isinf(f): 120d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise TypeError("Cannot convert %r to Fraction." % f) 121d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(*f.as_integer_ratio()) 122d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 12374d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson @staticmethod 12474d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson def from_decimal(dec): 12545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """Converts a finite Decimal instance to a rational number, exactly.""" 12645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin from decimal import Decimal 12745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if not isinstance(dec, Decimal): 12845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin raise TypeError( 129d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson "Fraction.from_decimal() only takes Decimals, not %r (%s)" % 13074d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson (dec, type(dec).__name__)) 13145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if not dec.is_finite(): 13245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Catches infinities and nans. 133d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson raise TypeError("Cannot convert %s to Fraction." % dec) 13445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin sign, digits, exp = dec.as_tuple() 13545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin digits = int(''.join(map(str, digits))) 13645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if sign: 13745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin digits = -digits 13845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if exp >= 0: 139d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(digits * 10 ** exp) 14045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin else: 141d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(digits, 10 ** -exp) 14245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 14374d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson @staticmethod 14474d09144136e6b6cc072765fa052dd85f69dcde9Mark Dickinson def from_continued_fraction(seq): 145d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson 'Build a Fraction from a continued fraction expessed as a sequence' 146cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = 1, 0 147cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger for e in reversed(seq): 148cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = d, n 149cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n += e * d 150d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(n, d) if seq else Fraction(0) 151cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 152cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger def as_continued_fraction(self): 153cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 'Return continued fraction expressed as a list' 154cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n = self.numerator 155cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger d = self.denominator 156cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger cf = [] 157cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger while d: 158cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger e = int(n // d) 159cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger cf.append(e) 160cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n -= e * d 161cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = d, n 162cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger return cf 163cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 1649c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger def approximate(self, max_denominator): 1659c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger 'Best rational approximation with a denominator <= max_denominator' 166cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # XXX First cut at algorithm 167cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # Still needs rounding rules as specified at 168cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # http://en.wikipedia.org/wiki/Continued_fraction 1699c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger if self.denominator <= max_denominator: 1709c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger return self 1719c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger cf = self.as_continued_fraction() 172d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson result = Fraction(0) 173cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger for i in range(1, len(cf)): 1749c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger new = self.from_continued_fraction(cf[:i]) 175cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger if new.denominator > max_denominator: 176cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger break 177cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger result = new 178cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger return result 179cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 180dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin @property 181dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin def numerator(a): 182dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin return a._numerator 183dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin 184dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin @property 185dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin def denominator(a): 186dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin return a._denominator 187dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin 188d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __repr__(self): 189d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """repr(self)""" 190d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return ('Fraction(%r,%r)' % (self.numerator, self.denominator)) 191d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 192d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __str__(self): 193d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """str(self)""" 194d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self.denominator == 1: 195d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return str(self.numerator) 196d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 19745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return '%s/%s' % (self.numerator, self.denominator) 198d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 199d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _operator_fallbacks(monomorphic_operator, fallback_operator): 200d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """Generates forward and reverse operators given a purely-rational 201d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin operator and a function from the operator module. 202d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 203d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Use this like: 204d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op) 205d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 206b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin In general, we want to implement the arithmetic operations so 207b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin that mixed-mode operations either call an implementation whose 208b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin author knew about the types of both arguments, or convert both 209b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin to the nearest built in type and do the operation there. In 210d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fraction, that means that we define __add__ and __radd__ as: 211b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 212b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin def __add__(self, other): 2132df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # Both types have numerators/denominator attributes, 2142df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # so do the operation directly 215d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(other, (int, long, Fraction)): 216d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(self.numerator * other.denominator + 217b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin other.numerator * self.denominator, 218b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin self.denominator * other.denominator) 2192df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # float and complex don't have those operations, but we 2202df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # know about those types, so special case them. 221b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, float): 222b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return float(self) + other 223b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, complex): 224b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return complex(self) + other 2252df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # Let the other type take over. 2262df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger return NotImplemented 227b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 228b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin def __radd__(self, other): 229b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin # radd handles more types than add because there's 230b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin # nothing left to fall back to. 231d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(other, Rational): 232d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(self.numerator * other.denominator + 233b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin other.numerator * self.denominator, 234b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin self.denominator * other.denominator) 235b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, Real): 236b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return float(other) + float(self) 237b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, Complex): 238b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return complex(other) + complex(self) 2392df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger return NotImplemented 240b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 241b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 242b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin There are 5 different cases for a mixed-type addition on 243d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fraction. I'll refer to all of the above code that doesn't 244d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson refer to Fraction, float, or complex as "boilerplate". 'r' 245d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson will be an instance of Fraction, which is a subtype of 246d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Rational (r : Fraction <: Rational), and b : B <: 247b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Complex. The first three involve 'r + b': 248b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 249d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson 1. If B <: Fraction, int, float, or complex, we handle 250b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin that specially, and all is well. 251d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson 2. If Fraction falls back to the boilerplate code, and it 252b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin were to return a value from __add__, we'd miss the 253b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin possibility that B defines a more intelligent __radd__, 254b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin so the boilerplate should return NotImplemented from 255d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson __add__. In particular, we don't handle Rational 256b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin here, even though we could get an exact answer, in case 257b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin the other type wants to do something special. 258d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson 3. If B <: Fraction, Python tries B.__radd__ before 259d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson Fraction.__add__. This is ok, because it was 260d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson implemented with knowledge of Fraction, so it can 261b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin handle those instances before delegating to Real or 262b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Complex. 263b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 264b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin The next two situations describe 'b + r'. We assume that b 265d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson didn't know about Fraction in its implementation, and that it 266b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin uses similar boilerplate code: 267b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 268d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson 4. If B <: Rational, then __radd_ converts both to the 269b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin builtin rational type (hey look, that's us) and 270b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin proceeds. 271b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 5. Otherwise, __radd__ tries to find the nearest common 272b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin base ABC, and fall back to its builtin type. Since this 273b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin class doesn't subclass a concrete type, there's no 274b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin implementation to fall back to, so we need to try as 275b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin hard as possible to return an actual value, or the user 276b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin will get a TypeError. 277b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 278d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 279d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def forward(a, b): 280d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(b, (int, long, Fraction)): 281d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return monomorphic_operator(a, b) 282d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(b, float): 283d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(float(a), b) 284d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(b, complex): 285d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(complex(a), b) 286d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 287d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 288d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin forward.__name__ = '__' + fallback_operator.__name__ + '__' 289d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin forward.__doc__ = monomorphic_operator.__doc__ 290d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 291d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def reverse(b, a): 292d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(a, Rational): 293d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Includes ints. 294d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return monomorphic_operator(a, b) 295d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(a, numbers.Real): 296d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(float(a), float(b)) 297d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(a, numbers.Complex): 298d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(complex(a), complex(b)) 299d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 300d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 301d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin reverse.__name__ = '__r' + fallback_operator.__name__ + '__' 302d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin reverse.__doc__ = monomorphic_operator.__doc__ 303d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 304d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return forward, reverse 305d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 306d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _add(a, b): 307d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a + b""" 308d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator * b.denominator + 309d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b.numerator * a.denominator, 310d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.denominator) 311d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 312d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __add__, __radd__ = _operator_fallbacks(_add, operator.add) 313d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 314d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _sub(a, b): 315d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a - b""" 316d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator * b.denominator - 317d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b.numerator * a.denominator, 318d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.denominator) 319d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 320d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) 321d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 322d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _mul(a, b): 323d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a * b""" 324d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator * b.numerator, a.denominator * b.denominator) 325d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 326d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul) 327d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 328d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _div(a, b): 329d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a / b""" 330d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator * b.denominator, 331d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.numerator) 332d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 333d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv) 334d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __div__, __rdiv__ = _operator_fallbacks(_div, operator.div) 335d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 336909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger def __floordiv__(a, b): 337909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger """a // b""" 338909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # Will be math.floor(a / b) in 3.0. 339d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin div = a / b 340d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(div, Rational): 341d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # trunc(math.floor(div)) doesn't work if the rational is 342d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # more precise than a float because the intermediate 343d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # rounding may cross an integer boundary. 344d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return div.numerator // div.denominator 345d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 346d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return math.floor(div) 347d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 348d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rfloordiv__(b, a): 349d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a // b""" 350d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Will be math.floor(a / b) in 3.0. 351909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a / b 352d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(div, Rational): 353909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # trunc(math.floor(div)) doesn't work if the rational is 354909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # more precise than a float because the intermediate 355909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # rounding may cross an integer boundary. 356909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return div.numerator // div.denominator 357909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger else: 358909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return math.floor(div) 359d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 360d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __mod__(a, b): 361d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a % b""" 362909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a // b 363909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return a - b * div 364d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 365d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rmod__(b, a): 366d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a % b""" 367909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a // b 368909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return a - b * div 369d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 370d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __pow__(a, b): 371d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a ** b 372d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 373d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin If b is not an integer, the result will be a float or complex 374d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin since roots are generally irrational. If b is an integer, the 375d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin result will be rational. 376d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 377d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 378d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(b, Rational): 379d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1: 380d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin power = b.numerator 381d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if power >= 0: 382d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator ** power, 383d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator ** power) 384d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 385d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.denominator ** -power, 386d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.numerator ** -power) 387d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 388d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # A fractional power will generally produce an 389d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # irrational number. 390d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) ** float(b) 391d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 392d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) ** b 393d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 394d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rpow__(b, a): 395d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a ** b""" 396d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1 and b.numerator >= 0: 397d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # If a is an int, keep it that way if possible. 398d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** b.numerator 399d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 400d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(a, Rational): 401d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator, a.denominator) ** b 402d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 403d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1: 404d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** b.numerator 405d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 406d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** float(b) 407d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 408d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __pos__(a): 409d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson """+a: Coerces a subclass instance to Fraction""" 410d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(a.numerator, a.denominator) 411d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 412d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __neg__(a): 413d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """-a""" 414d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(-a.numerator, a.denominator) 415d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 416d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __abs__(a): 417d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """abs(a)""" 418d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson return Fraction(abs(a.numerator), a.denominator) 419d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 420d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __trunc__(a): 421d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """trunc(a)""" 422d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if a.numerator < 0: 423d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return -(-a.numerator // a.denominator) 424d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 425d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a.numerator // a.denominator 426d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 427d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __hash__(self): 428d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """hash(self) 429d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 430d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Tricky because values that are exactly representable as a 431d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin float must have the same hash as that float. 432d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 433d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 434921cb5d3a3e823c6c225681d8e99f7baa8920f3eRaymond Hettinger # XXX since this method is expensive, consider caching the result 435d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self.denominator == 1: 436d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Get integers right. 437d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash(self.numerator) 438d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Expensive check, but definitely correct. 439d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self == float(self): 440d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash(float(self)) 441d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 442d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Use tuple's hash to avoid a high collision rate on 443d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # simple fractions. 444d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash((self.numerator, self.denominator)) 445d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 446d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __eq__(a, b): 447d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a == b""" 448d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(b, Rational): 449d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return (a.numerator == b.numerator and 450d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator == b.denominator) 451d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, numbers.Complex) and b.imag == 0: 452d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = b.real 453d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, float): 454d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a == a.from_float(b) 455d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 456d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # XXX: If b.__eq__ is implemented like this method, it may 457d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # give the wrong answer after float(a) changes a's 458d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # value. Better ways of doing this are welcome. 459d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) == b 460d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 461d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _subtractAndCompareToZero(a, b, op): 462d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """Helper function for comparison operators. 463d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 464d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Subtracts b from a, exactly if possible, and compares the 465d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin result with 0 using op, in such a way that the comparison 466d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin won't recurse. If the difference raises a TypeError, returns 467d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin NotImplemented instead. 468d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 469d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 470d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, numbers.Complex) and b.imag == 0: 471d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = b.real 472d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, float): 473d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = a.from_float(b) 474d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin try: 475d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson # XXX: If b <: Real but not <: Rational, this is likely 476d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # to fall back to a float. If the actual values differ by 477d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # less than MIN_FLOAT, this could falsely call them equal, 478d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # which would make <= inconsistent with ==. Better ways of 479d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # doing this are welcome. 480d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin diff = a - b 481d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin except TypeError: 482d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 483d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if isinstance(diff, Rational): 484d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return op(diff.numerator, 0) 485d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return op(diff, 0) 486d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 487d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __lt__(a, b): 488d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a < b""" 489d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.lt) 490d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 491d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __gt__(a, b): 492d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a > b""" 493d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.gt) 494d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 495d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __le__(a, b): 496d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a <= b""" 497d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.le) 498d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 499d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __ge__(a, b): 500d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a >= b""" 501d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.ge) 502d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 503d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __nonzero__(a): 504d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a != 0""" 505d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a.numerator != 0 506a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 507a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger # support for pickling, copy, and deepcopy 508a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 509a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __reduce__(self): 510a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return (self.__class__, (str(self),)) 511a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 512a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __copy__(self): 513d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if type(self) == Fraction: 514a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self # I'm immutable; therefore I am my own clone 515a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self.__class__(self.numerator, self.denominator) 516a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 517a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __deepcopy__(self, memo): 518d058cd2cc8e2a3f61609b92a8fc821ea8ec524caMark Dickinson if type(self) == Fraction: 519a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self # My components are also immutable 520a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self.__class__(self.numerator, self.denominator) 521