cinap_lenrekadd hg and python4bb9e2215 years agoHistory
310 lines · 8.6 KB · Python
RawDownload
'''\This module implements rational numbers. The entry point of this module is the function        rat(numerator, denominator)If either numerator or denominator is of an integral or rational type,the result is a rational number, else, the result is the simplest ofthe types float and complex which can hold numerator/denominator.If denominator is omitted, it defaults to 1.Rational numbers can be used in calculations with any other numerictype.  The result of the calculation will be rational if possible. There is also a test function with calling sequence        test()The documentation string of the test function contains the expectedoutput.''' # Contributed by Sjoerd Mullender from types import * def gcd(a, b):    '''Calculate the Greatest Common Divisor.'''    while b:        a, b = b, a%b    return a def rat(num, den = 1):    # must check complex before float    if isinstance(num, complex) or isinstance(den, complex):        # numerator or denominator is complex: return a complex        return complex(num) / complex(den)    if isinstance(num, float) or isinstance(den, float):        # numerator or denominator is float: return a float        return float(num) / float(den)    # otherwise return a rational    return Rat(num, den) class Rat:    '''This class implements rational numbers.'''     def __init__(self, num, den = 1):        if den == 0:            raise ZeroDivisionError, 'rat(x, 0)'         # normalize         # must check complex before float        if (isinstance(num, complex) or            isinstance(den, complex)):            # numerator or denominator is complex:            # normalized form has denominator == 1+0j            self.__num = complex(num) / complex(den)            self.__den = complex(1)            return        if isinstance(num, float) or isinstance(den, float):            # numerator or denominator is float:            # normalized form has denominator == 1.0            self.__num = float(num) / float(den)            self.__den = 1.0            return        if (isinstance(num, self.__class__) or            isinstance(den, self.__class__)):            # numerator or denominator is rational            new = num / den            if not isinstance(new, self.__class__):                self.__num = new                if isinstance(new, complex):                    self.__den = complex(1)                else:                    self.__den = 1.0            else:                self.__num = new.__num                self.__den = new.__den        else:            # make sure numerator and denominator don't            # have common factors            # this also makes sure that denominator > 0            g = gcd(num, den)            self.__num = num / g            self.__den = den / g        # try making numerator and denominator of IntType if they fit        try:            numi = int(self.__num)            deni = int(self.__den)        except (OverflowError, TypeError):            pass        else:            if self.__num == numi and self.__den == deni:                self.__num = numi                self.__den = deni     def __repr__(self):        return 'Rat(%s,%s)' % (self.__num, self.__den)     def __str__(self):        if self.__den == 1:            return str(self.__num)        else:            return '(%s/%s)' % (str(self.__num), str(self.__den))     # a + b    def __add__(a, b):        try:            return rat(a.__num * b.__den + b.__num * a.__den,                       a.__den * b.__den)        except OverflowError:            return rat(long(a.__num) * long(b.__den) +                       long(b.__num) * long(a.__den),                       long(a.__den) * long(b.__den))     def __radd__(b, a):        return Rat(a) + b     # a - b    def __sub__(a, b):        try:            return rat(a.__num * b.__den - b.__num * a.__den,                       a.__den * b.__den)        except OverflowError:            return rat(long(a.__num) * long(b.__den) -                       long(b.__num) * long(a.__den),                       long(a.__den) * long(b.__den))     def __rsub__(b, a):        return Rat(a) - b     # a * b    def __mul__(a, b):        try:            return rat(a.__num * b.__num, a.__den * b.__den)        except OverflowError:            return rat(long(a.__num) * long(b.__num),                       long(a.__den) * long(b.__den))     def __rmul__(b, a):        return Rat(a) * b     # a / b    def __div__(a, b):        try:            return rat(a.__num * b.__den, a.__den * b.__num)        except OverflowError:            return rat(long(a.__num) * long(b.__den),                       long(a.__den) * long(b.__num))     def __rdiv__(b, a):        return Rat(a) / b     # a % b    def __mod__(a, b):        div = a / b        try:            div = int(div)        except OverflowError:            div = long(div)        return a - b * div     def __rmod__(b, a):        return Rat(a) % b     # a ** b    def __pow__(a, b):        if b.__den != 1:            if isinstance(a.__num, complex):                a = complex(a)            else:                a = float(a)            if isinstance(b.__num, complex):                b = complex(b)            else:                b = float(b)            return a ** b        try:            return rat(a.__num ** b.__num, a.__den ** b.__num)        except OverflowError:            return rat(long(a.__num) ** b.__num,                       long(a.__den) ** b.__num)     def __rpow__(b, a):        return Rat(a) ** b     # -a    def __neg__(a):        try:            return rat(-a.__num, a.__den)        except OverflowError:            # a.__num == sys.maxint            return rat(-long(a.__num), a.__den)     # abs(a)    def __abs__(a):        return rat(abs(a.__num), a.__den)     # int(a)    def __int__(a):        return int(a.__num / a.__den)     # long(a)    def __long__(a):        return long(a.__num) / long(a.__den)     # float(a)    def __float__(a):        return float(a.__num) / float(a.__den)     # complex(a)    def __complex__(a):        return complex(a.__num) / complex(a.__den)     # cmp(a,b)    def __cmp__(a, b):        diff = Rat(a - b)        if diff.__num < 0:            return -1        elif diff.__num > 0:            return 1        else:            return 0     def __rcmp__(b, a):        return cmp(Rat(a), b)     # a != 0    def __nonzero__(a):        return a.__num != 0     # coercion    def __coerce__(a, b):        return a, Rat(b) def test():    '''\    Test function for rat module.     The expected output is (module some differences in floating    precission):    -1    -1    0 0L 0.1 (0.1+0j)    [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]    [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]    0    (11/10)    (11/10)    1.1    OK    2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)    2 2 2.0 (2+0j)     4 0 4 1 4 0    3.5 0.5 3.0 1.33333333333 2.82842712475 1    (7/2) (1/2) 3 (4/3) 2.82842712475 1    (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1    1.5 1 1.5 (1.5+0j)     3.5 -0.5 3.0 0.75 2.25 -1    3.0 0.0 2.25 1.0 1.83711730709 0    3.0 0.0 2.25 1.0 1.83711730709 1    (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1    (3/2) 1 1.5 (1.5+0j)     (7/2) (-1/2) 3 (3/4) (9/4) -1    3.0 0.0 2.25 1.0 1.83711730709 -1    3 0 (9/4) 1 1.83711730709 0    (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1    (1.5+1.5j) (1.5+1.5j)     (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1    (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1    (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1    (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0    '''    print rat(-1L, 1)    print rat(1, -1)    a = rat(1, 10)    print int(a), long(a), float(a), complex(a)    b = rat(2, 5)    l = [a+b, a-b, a*b, a/b]    print l    l.sort()    print l    print rat(0, 1)    print a+1    print a+1L    print a+1.0    try:        print rat(1, 0)        raise SystemError, 'should have been ZeroDivisionError'    except ZeroDivisionError:        print 'OK'    print rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000)    list = [2, 1.5, rat(3,2), 1.5+1.5j]    for i in list:        print i,        if not isinstance(i, complex):            print int(i), float(i),        print complex(i)        print        for j in list:            print i + j, i - j, i * j, i / j, i ** j,            if not (isinstance(i, complex) or                    isinstance(j, complex)):                print cmp(i, j)            print  if __name__ == '__main__':    test()