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