blob: 55543b6d2d249391b6da9e6c0c9e0c4e887c1ef1 [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:
45 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:
109 return rat(long(a.__num) * long(b.__den) +
110 long(b.__num) * long(a.__den),
111 long(a.__den) * long(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:
122 return rat(long(a.__num) * long(b.__den) -
123 long(b.__num) * long(a.__den),
124 long(a.__den) * long(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:
134 return rat(long(a.__num) * long(b.__num),
135 long(a.__den) * long(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:
145 return rat(long(a.__num) * long(b.__den),
146 long(a.__den) * long(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:
157 div = long(div)
158 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:
178 return rat(long(a.__num) ** b.__num,
179 long(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
190 return rat(-long(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):
202 return long(a.__num) / long(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
226 def __nonzero__(a):
227 return a.__num != 0
Guido van Rossum0609f191997-05-13 19:25:57 +0000228
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000229 # coercion
230 def __coerce__(a, b):
231 return a, Rat(b)
Guido van Rossume8769491992-08-13 12:14:11 +0000232
233def test():
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000234 '''\
235 Test function for rat module.
Guido van Rossum0609f191997-05-13 19:25:57 +0000236
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000237 The expected output is (module some differences in floating
238 precission):
239 -1
240 -1
241 0 0L 0.1 (0.1+0j)
242 [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
243 [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
244 0
245 (11/10)
246 (11/10)
247 1.1
248 OK
249 2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
250 2 2 2.0 (2+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000251
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000252 4 0 4 1 4 0
253 3.5 0.5 3.0 1.33333333333 2.82842712475 1
254 (7/2) (1/2) 3 (4/3) 2.82842712475 1
255 (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
256 1.5 1 1.5 (1.5+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000257
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000258 3.5 -0.5 3.0 0.75 2.25 -1
259 3.0 0.0 2.25 1.0 1.83711730709 0
260 3.0 0.0 2.25 1.0 1.83711730709 1
261 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
262 (3/2) 1 1.5 (1.5+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000263
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000264 (7/2) (-1/2) 3 (3/4) (9/4) -1
265 3.0 0.0 2.25 1.0 1.83711730709 -1
266 3 0 (9/4) 1 1.83711730709 0
267 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
268 (1.5+1.5j) (1.5+1.5j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000269
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000270 (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
271 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
272 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
273 (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
274 '''
275 print rat(-1L, 1)
276 print rat(1, -1)
277 a = rat(1, 10)
278 print int(a), long(a), float(a), complex(a)
279 b = rat(2, 5)
280 l = [a+b, a-b, a*b, a/b]
281 print l
282 l.sort()
283 print l
284 print rat(0, 1)
285 print a+1
286 print a+1L
287 print a+1.0
288 try:
289 print rat(1, 0)
290 raise SystemError, 'should have been ZeroDivisionError'
291 except ZeroDivisionError:
292 print 'OK'
293 print rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000)
294 list = [2, 1.5, rat(3,2), 1.5+1.5j]
295 for i in list:
296 print i,
297 if not isinstance(i, complex):
298 print int(i), float(i),
299 print complex(i)
300 print
301 for j in list:
302 print i + j, i - j, i * j, i / j, i ** j,
303 if not (isinstance(i, complex) or
304 isinstance(j, complex)):
305 print cmp(i, j)
306 print
Andrew M. Kuchling64b3c832003-04-24 16:59:45 +0000307
Guido van Rossume8769491992-08-13 12:14:11 +0000308
Guido van Rossum0609f191997-05-13 19:25:57 +0000309if __name__ == '__main__':
310 test()