Guido van Rossum | e876949 | 1992-08-13 12:14:11 +0000 | [diff] [blame] | 1 | # Rational numbers |
| 2 | |
| 3 | |
| 4 | def rat(num, den): |
| 5 | return Rat().init(num, den) |
| 6 | |
| 7 | |
| 8 | def gcd(a, b): |
| 9 | while b: |
| 10 | a, b = b, a%b |
| 11 | return a |
| 12 | |
| 13 | |
| 14 | class Rat: |
| 15 | |
| 16 | def init(self, num, den): |
| 17 | if den == 0: |
| 18 | raise ZeroDivisionError, 'rat(x, 0)' |
| 19 | g = gcd(num, den) |
| 20 | self.num = num/g |
| 21 | self.den = den/g |
| 22 | return self |
| 23 | |
| 24 | def __repr__(self): |
| 25 | return 'rat' + `self.num, self.den` |
| 26 | |
| 27 | def __cmp__(a, b): |
| 28 | c = a-b |
| 29 | if c.num < 0: |
| 30 | return -1 |
| 31 | if c.num > 0: |
| 32 | return 1 |
| 33 | return 0 |
| 34 | |
| 35 | def __float__(self): |
| 36 | return float(self.num) / float(self.den) |
| 37 | |
| 38 | def __long__(self): |
| 39 | return long(self.num) / long(self.den) |
| 40 | |
| 41 | def __int__(self): |
| 42 | return int(self.num / self.den) |
| 43 | |
| 44 | def __coerce__(a, b): |
| 45 | t = type(b) |
| 46 | if t == type(0): |
| 47 | return a, rat(b, 1) |
| 48 | if t == type(0L): |
| 49 | return a, rat(b, 1L) |
| 50 | if t == type(0.0): |
| 51 | return a.__float__(), b |
| 52 | raise TypeError, 'Rat.__coerce__: bad other arg' |
| 53 | |
| 54 | def __add__(a, b): |
Guido van Rossum | f1bbf9c | 1993-10-27 09:28:23 +0000 | [diff] [blame] | 55 | if type(b) <> type(a): |
| 56 | a, b = a.__coerce__(b) |
| 57 | return a + b |
Guido van Rossum | e876949 | 1992-08-13 12:14:11 +0000 | [diff] [blame] | 58 | return rat(a.num*b.den + b.num*a.den, a.den*b.den) |
| 59 | |
| 60 | def __sub__(a, b): |
| 61 | return rat(a.num*b.den - b.num*a.den, a.den*b.den) |
| 62 | |
| 63 | def __mul__(a, b): |
Guido van Rossum | f1bbf9c | 1993-10-27 09:28:23 +0000 | [diff] [blame] | 64 | if type(b) <> type(a): |
| 65 | a, b = a.__coerce__(b) |
| 66 | return a * b |
Guido van Rossum | e876949 | 1992-08-13 12:14:11 +0000 | [diff] [blame] | 67 | return rat(a.num*b.num, a.den*b.den) |
| 68 | |
| 69 | def __div__(a, b): |
| 70 | return rat(a.num*b.den, a.den*b.num) |
| 71 | |
| 72 | def __neg__(self): |
| 73 | return rat(-self.num, self.den) |
| 74 | |
| 75 | |
| 76 | def test(): |
| 77 | print rat(-1L, 1) |
| 78 | print rat(1, -1) |
| 79 | a = rat(1, 10) |
| 80 | print int(a), long(a), float(a) |
| 81 | b = rat(2, 5) |
| 82 | l = [a+b, a-b, a*b, a/b] |
| 83 | print l |
| 84 | l.sort() |
| 85 | print l |
| 86 | print rat(0, 1) |
Guido van Rossum | e876949 | 1992-08-13 12:14:11 +0000 | [diff] [blame] | 87 | print a+1 |
| 88 | print a+1L |
| 89 | print a+1.0 |
Guido van Rossum | f1bbf9c | 1993-10-27 09:28:23 +0000 | [diff] [blame] | 90 | try: |
| 91 | print rat(1, 0) |
| 92 | raise SystemError, 'should have been ZeroDivisionError' |
| 93 | except ZeroDivisionError: |
| 94 | print 'OK' |
Guido van Rossum | e876949 | 1992-08-13 12:14:11 +0000 | [diff] [blame] | 95 | |
Guido van Rossum | f1bbf9c | 1993-10-27 09:28:23 +0000 | [diff] [blame] | 96 | #test() |