blob: 6a350e8a8115752574912252ac5b854e0abad2e3 [file] [log] [blame]
Guido van Rossum0609f191997-05-13 19:25:57 +00001'''\
2This module implements rational numbers.
3
4The entry point of this module is the function
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +00005 rat(numerator, denominator)
Guido van Rossum0609f191997-05-13 19:25:57 +00006If either numerator or denominator is of an integral or rational type,
7the result is a rational number, else, the result is the simplest of
8the types float and complex which can hold numerator/denominator.
9If denominator is omitted, it defaults to 1.
10Rational numbers can be used in calculations with any other numeric
11type. The result of the calculation will be rational if possible.
12
13There is also a test function with calling sequence
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000014 test()
Guido van Rossum0609f191997-05-13 19:25:57 +000015The documentation string of the test function contains the expected
16output.
17'''
18
19# Contributed by Sjoerd Mullender
Guido van Rossume8769491992-08-13 12:14:11 +000020
Guido van Rossum2e611031994-10-09 22:36:28 +000021from types import *
Guido van Rossume8769491992-08-13 12:14:11 +000022
Guido van Rossume8769491992-08-13 12:14:11 +000023def gcd(a, b):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000024 '''Calculate the Greatest Common Divisor.'''
25 while b:
26 a, b = b, a%b
27 return a
Guido van Rossume8769491992-08-13 12:14:11 +000028
Guido van Rossum0609f191997-05-13 19:25:57 +000029def rat(num, den = 1):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000030 # must check complex before float
31 if isinstance(num, complex) or isinstance(den, complex):
32 # numerator or denominator is complex: return a complex
33 return complex(num) / complex(den)
34 if isinstance(num, float) or isinstance(den, float):
35 # numerator or denominator is float: return a float
36 return float(num) / float(den)
37 # otherwise return a rational
38 return Rat(num, den)
Guido van Rossume8769491992-08-13 12:14:11 +000039
40class Rat:
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000041 '''This class implements rational numbers.'''
Guido van Rossume8769491992-08-13 12:14:11 +000042
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000043 def __init__(self, num, den = 1):
44 if den == 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000045 raise ZeroDivisionError('rat(x, 0)')
Guido van Rossum0609f191997-05-13 19:25:57 +000046
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000047 # normalize
Guido van Rossum0609f191997-05-13 19:25:57 +000048
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000049 # must check complex before float
50 if (isinstance(num, complex) or
51 isinstance(den, complex)):
52 # numerator or denominator is complex:
53 # normalized form has denominator == 1+0j
54 self.__num = complex(num) / complex(den)
55 self.__den = complex(1)
56 return
57 if isinstance(num, float) or isinstance(den, float):
58 # numerator or denominator is float:
59 # normalized form has denominator == 1.0
60 self.__num = float(num) / float(den)
61 self.__den = 1.0
62 return
63 if (isinstance(num, self.__class__) or
64 isinstance(den, self.__class__)):
65 # numerator or denominator is rational
66 new = num / den
67 if not isinstance(new, self.__class__):
68 self.__num = new
69 if isinstance(new, complex):
70 self.__den = complex(1)
71 else:
72 self.__den = 1.0
73 else:
74 self.__num = new.__num
75 self.__den = new.__den
76 else:
77 # make sure numerator and denominator don't
78 # have common factors
79 # this also makes sure that denominator > 0
80 g = gcd(num, den)
81 self.__num = num / g
82 self.__den = den / g
83 # try making numerator and denominator of IntType if they fit
84 try:
85 numi = int(self.__num)
86 deni = int(self.__den)
87 except (OverflowError, TypeError):
88 pass
89 else:
90 if self.__num == numi and self.__den == deni:
91 self.__num = numi
92 self.__den = deni
Guido van Rossume8769491992-08-13 12:14:11 +000093
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000094 def __repr__(self):
95 return 'Rat(%s,%s)' % (self.__num, self.__den)
Guido van Rossum2e611031994-10-09 22:36:28 +000096
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000097 def __str__(self):
98 if self.__den == 1:
99 return str(self.__num)
100 else:
101 return '(%s/%s)' % (str(self.__num), str(self.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000102
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000103 # a + b
104 def __add__(a, b):
105 try:
106 return rat(a.__num * b.__den + b.__num * a.__den,
107 a.__den * b.__den)
108 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000109 return rat(int(a.__num) * int(b.__den) +
110 int(b.__num) * int(a.__den),
111 int(a.__den) * int(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000112
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000113 def __radd__(b, a):
114 return Rat(a) + b
Guido van Rossum0609f191997-05-13 19:25:57 +0000115
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000116 # a - b
117 def __sub__(a, b):
118 try:
119 return rat(a.__num * b.__den - b.__num * a.__den,
120 a.__den * b.__den)
121 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000122 return rat(int(a.__num) * int(b.__den) -
123 int(b.__num) * int(a.__den),
124 int(a.__den) * int(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000125
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000126 def __rsub__(b, a):
127 return Rat(a) - b
Guido van Rossum0609f191997-05-13 19:25:57 +0000128
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000129 # a * b
130 def __mul__(a, b):
131 try:
132 return rat(a.__num * b.__num, a.__den * b.__den)
133 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000134 return rat(int(a.__num) * int(b.__num),
135 int(a.__den) * int(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000136
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000137 def __rmul__(b, a):
138 return Rat(a) * b
Guido van Rossum0609f191997-05-13 19:25:57 +0000139
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000140 # a / b
141 def __div__(a, b):
142 try:
143 return rat(a.__num * b.__den, a.__den * b.__num)
144 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000145 return rat(int(a.__num) * int(b.__den),
146 int(a.__den) * int(b.__num))
Guido van Rossume8769491992-08-13 12:14:11 +0000147
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000148 def __rdiv__(b, a):
149 return Rat(a) / b
Guido van Rossume8769491992-08-13 12:14:11 +0000150
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000151 # a % b
152 def __mod__(a, b):
153 div = a / b
154 try:
155 div = int(div)
156 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000157 div = int(div)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000158 return a - b * div
Guido van Rossum0609f191997-05-13 19:25:57 +0000159
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000160 def __rmod__(b, a):
161 return Rat(a) % b
Guido van Rossum0609f191997-05-13 19:25:57 +0000162
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000163 # a ** b
164 def __pow__(a, b):
165 if b.__den != 1:
166 if isinstance(a.__num, complex):
167 a = complex(a)
168 else:
169 a = float(a)
170 if isinstance(b.__num, complex):
171 b = complex(b)
172 else:
173 b = float(b)
174 return a ** b
175 try:
176 return rat(a.__num ** b.__num, a.__den ** b.__num)
177 except OverflowError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000178 return rat(int(a.__num) ** b.__num,
179 int(a.__den) ** b.__num)
Guido van Rossum0609f191997-05-13 19:25:57 +0000180
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000181 def __rpow__(b, a):
182 return Rat(a) ** b
Guido van Rossum0609f191997-05-13 19:25:57 +0000183
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000184 # -a
185 def __neg__(a):
186 try:
187 return rat(-a.__num, a.__den)
188 except OverflowError:
189 # a.__num == sys.maxint
Collin Winter6f2df4d2007-07-17 20:59:35 +0000190 return rat(-int(a.__num), a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000191
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000192 # abs(a)
193 def __abs__(a):
194 return rat(abs(a.__num), a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000195
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000196 # int(a)
197 def __int__(a):
198 return int(a.__num / a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000199
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000200 # long(a)
201 def __long__(a):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000202 return int(a.__num) / int(a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000203
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000204 # float(a)
205 def __float__(a):
206 return float(a.__num) / float(a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000207
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000208 # complex(a)
209 def __complex__(a):
210 return complex(a.__num) / complex(a.__den)
Guido van Rossum0609f191997-05-13 19:25:57 +0000211
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000212 # cmp(a,b)
213 def __cmp__(a, b):
214 diff = Rat(a - b)
215 if diff.__num < 0:
216 return -1
217 elif diff.__num > 0:
218 return 1
219 else:
220 return 0
Guido van Rossum0609f191997-05-13 19:25:57 +0000221
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000222 def __rcmp__(b, a):
223 return cmp(Rat(a), b)
Guido van Rossum0609f191997-05-13 19:25:57 +0000224
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000225 # a != 0
Jack Diederich4dafcc42006-11-28 19:15:13 +0000226 def __bool__(a):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000227 return a.__num != 0
Guido van Rossum0609f191997-05-13 19:25:57 +0000228
Guido van Rossume8769491992-08-13 12:14:11 +0000229def test():
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000230 '''\
231 Test function for rat module.
Guido van Rossum0609f191997-05-13 19:25:57 +0000232
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000233 The expected output is (module some differences in floating
234 precission):
235 -1
236 -1
237 0 0L 0.1 (0.1+0j)
238 [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
239 [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
240 0
241 (11/10)
242 (11/10)
243 1.1
244 OK
245 2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
246 2 2 2.0 (2+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000247
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000248 4 0 4 1 4 0
249 3.5 0.5 3.0 1.33333333333 2.82842712475 1
250 (7/2) (1/2) 3 (4/3) 2.82842712475 1
251 (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
252 1.5 1 1.5 (1.5+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000253
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000254 3.5 -0.5 3.0 0.75 2.25 -1
255 3.0 0.0 2.25 1.0 1.83711730709 0
256 3.0 0.0 2.25 1.0 1.83711730709 1
257 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
258 (3/2) 1 1.5 (1.5+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000259
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000260 (7/2) (-1/2) 3 (3/4) (9/4) -1
261 3.0 0.0 2.25 1.0 1.83711730709 -1
262 3 0 (9/4) 1 1.83711730709 0
263 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
264 (1.5+1.5j) (1.5+1.5j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000265
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000266 (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
267 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
268 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
269 (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
270 '''
Collin Winter6f2df4d2007-07-17 20:59:35 +0000271 print(rat(-1, 1))
272 print(rat(1, -1))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000273 a = rat(1, 10)
Collin Winter6f2df4d2007-07-17 20:59:35 +0000274 print(int(a), int(a), float(a), complex(a))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000275 b = rat(2, 5)
276 l = [a+b, a-b, a*b, a/b]
Collin Winter6f2df4d2007-07-17 20:59:35 +0000277 print(l)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000278 l.sort()
Collin Winter6f2df4d2007-07-17 20:59:35 +0000279 print(l)
280 print(rat(0, 1))
281 print(a+1)
282 print(a+1)
283 print(a+1.0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000284 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000285 print(rat(1, 0))
286 raise SystemError('should have been ZeroDivisionError')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000287 except ZeroDivisionError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000288 print('OK')
289 print(rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000290 list = [2, 1.5, rat(3,2), 1.5+1.5j]
291 for i in list:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000292 print(i, end=' ')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000293 if not isinstance(i, complex):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000294 print(int(i), float(i), end=' ')
295 print(complex(i))
296 print()
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000297 for j in list:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000298 print(i + j, i - j, i * j, i / j, i ** j, end=' ')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000299 if not (isinstance(i, complex) or
300 isinstance(j, complex)):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000301 print(cmp(i, j))
302 print()
Andrew M. Kuchling64b3c832003-04-24 16:59:45 +0000303
Guido van Rossume8769491992-08-13 12:14:11 +0000304
Guido van Rossum0609f191997-05-13 19:25:57 +0000305if __name__ == '__main__':
306 test()