blob: 4fc4a1786f1f447c272d884598d2b0c65c21a1b2 [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
5 rat(numerator, denominator)
6If 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
14 test()
15The 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):
Guido van Rossum0609f191997-05-13 19:25:57 +000024 '''Calculate the Greatest Common Divisor.'''
Guido van Rossume8769491992-08-13 12:14:11 +000025 while b:
26 a, b = b, a%b
27 return a
28
Guido van Rossum0609f191997-05-13 19:25:57 +000029def rat(num, den = 1):
30 # must check complex before float
31 if type(num) is ComplexType or type(den) is ComplexType:
32 # numerator or denominator is complex: return a complex
33 return complex(num) / complex(den)
34 if type(num) is FloatType or type(den) is FloatType:
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:
Guido van Rossum0609f191997-05-13 19:25:57 +000041 '''This class implements rational numbers.'''
Guido van Rossume8769491992-08-13 12:14:11 +000042
Guido van Rossum0609f191997-05-13 19:25:57 +000043 def __init__(self, num, den = 1):
Guido van Rossume8769491992-08-13 12:14:11 +000044 if den == 0:
45 raise ZeroDivisionError, 'rat(x, 0)'
Guido van Rossum0609f191997-05-13 19:25:57 +000046
47 # normalize
48
49 # must check complex before float
50 if type(num) is ComplexType or type(den) is ComplexType:
51 # numerator or denominator is complex:
52 # normalized form has denominator == 1+0j
53 self.__num = complex(num) / complex(den)
54 self.__den = complex(1)
55 return
56 if type(num) is FloatType or type(den) is FloatType:
57 # numerator or denominator is float:
58 # normalized form has denominator == 1.0
59 self.__num = float(num) / float(den)
60 self.__den = 1.0
61 return
62 if (type(num) is InstanceType and
63 num.__class__ is self.__class__) or \
64 (type(den) is InstanceType and
65 den.__class__ is self.__class__):
66 # numerator or denominator is rational
67 new = num / den
68 if type(new) is not InstanceType or \
69 new.__class__ is not self.__class__:
70 self.__num = new
71 if type(new) is ComplexType:
72 self.__den = complex(1)
73 else:
74 self.__den = 1.0
75 else:
76 self.__num = new.__num
77 self.__den = new.__den
Guido van Rossum2e611031994-10-09 22:36:28 +000078 else:
Guido van Rossum0609f191997-05-13 19:25:57 +000079 # make sure numerator and denominator don't
80 # have common factors
81 # this also makes sure that denominator > 0
Guido van Rossum2e611031994-10-09 22:36:28 +000082 g = gcd(num, den)
Guido van Rossum0609f191997-05-13 19:25:57 +000083 self.__num = num / g
84 self.__den = den / g
85 # try making numerator and denominator of IntType if they fit
86 try:
87 numi = int(self.__num)
88 deni = int(self.__den)
89 except (OverflowError, TypeError):
90 pass
91 else:
92 if self.__num == numi and self.__den == deni:
93 self.__num = numi
94 self.__den = deni
Guido van Rossume8769491992-08-13 12:14:11 +000095
96 def __repr__(self):
Guido van Rossum0609f191997-05-13 19:25:57 +000097 return 'Rat(%s,%s)' % (self.__num, self.__den)
Guido van Rossum2e611031994-10-09 22:36:28 +000098
99 def __str__(self):
Guido van Rossum0609f191997-05-13 19:25:57 +0000100 if self.__den == 1:
101 return str(self.__num)
Guido van Rossum2e611031994-10-09 22:36:28 +0000102 else:
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000103 return '(%s/%s)' % (str(self.__num), str(self.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000104
Guido van Rossum0609f191997-05-13 19:25:57 +0000105 # a + b
Guido van Rossume8769491992-08-13 12:14:11 +0000106 def __add__(a, b):
Guido van Rossum0609f191997-05-13 19:25:57 +0000107 try:
108 return rat(a.__num * b.__den + b.__num * a.__den,
109 a.__den * b.__den)
110 except OverflowError:
111 return rat(long(a.__num) * long(b.__den) +
112 long(b.__num) * long(a.__den),
113 long(a.__den) * long(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000114
Guido van Rossum0609f191997-05-13 19:25:57 +0000115 def __radd__(b, a):
116 return Rat(a) + b
117
118 # a - b
Guido van Rossume8769491992-08-13 12:14:11 +0000119 def __sub__(a, b):
Guido van Rossum0609f191997-05-13 19:25:57 +0000120 try:
121 return rat(a.__num * b.__den - b.__num * a.__den,
122 a.__den * b.__den)
123 except OverflowError:
124 return rat(long(a.__num) * long(b.__den) -
125 long(b.__num) * long(a.__den),
126 long(a.__den) * long(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000127
Guido van Rossum0609f191997-05-13 19:25:57 +0000128 def __rsub__(b, a):
129 return Rat(a) - b
130
131 # a * b
Guido van Rossume8769491992-08-13 12:14:11 +0000132 def __mul__(a, b):
Guido van Rossum0609f191997-05-13 19:25:57 +0000133 try:
134 return rat(a.__num * b.__num, a.__den * b.__den)
135 except OverflowError:
136 return rat(long(a.__num) * long(b.__num),
137 long(a.__den) * long(b.__den))
Guido van Rossume8769491992-08-13 12:14:11 +0000138
Guido van Rossum0609f191997-05-13 19:25:57 +0000139 def __rmul__(b, a):
140 return Rat(a) * b
141
142 # a / b
Guido van Rossume8769491992-08-13 12:14:11 +0000143 def __div__(a, b):
Guido van Rossum0609f191997-05-13 19:25:57 +0000144 try:
145 return rat(a.__num * b.__den, a.__den * b.__num)
146 except OverflowError:
147 return rat(long(a.__num) * long(b.__den),
148 long(a.__den) * long(b.__num))
Guido van Rossume8769491992-08-13 12:14:11 +0000149
Guido van Rossum0609f191997-05-13 19:25:57 +0000150 def __rdiv__(b, a):
151 return Rat(a) / b
Guido van Rossume8769491992-08-13 12:14:11 +0000152
Guido van Rossum0609f191997-05-13 19:25:57 +0000153 # a % b
154 def __mod__(a, b):
155 div = a / b
156 try:
157 div = int(div)
158 except OverflowError:
159 div = long(div)
160 return a - b * div
161
162 def __rmod__(b, a):
163 return Rat(a) % b
164
165 # a ** b
166 def __pow__(a, b):
167 if b.__den != 1:
168 if type(a.__num) is ComplexType:
169 a = complex(a)
170 else:
171 a = float(a)
172 if type(b.__num) is ComplexType:
173 b = complex(b)
174 else:
175 b = float(b)
176 return a ** b
177 try:
178 return rat(a.__num ** b.__num, a.__den ** b.__num)
179 except OverflowError:
180 return rat(long(a.__num) ** b.__num,
181 long(a.__den) ** b.__num)
182
183 def __rpow__(b, a):
184 return Rat(a) ** b
185
186 # -a
187 def __neg__(a):
188 try:
189 return rat(-a.__num, a.__den)
190 except OverflowError:
191 # a.__num == sys.maxint
192 return rat(-long(a.__num), a.__den)
193
194 # abs(a)
195 def __abs__(a):
196 return rat(abs(a.__num), a.__den)
197
198 # int(a)
199 def __int__(a):
200 return int(a.__num / a.__den)
201
202 # long(a)
203 def __long__(a):
204 return long(a.__num) / long(a.__den)
205
206 # float(a)
207 def __float__(a):
208 return float(a.__num) / float(a.__den)
209
210 # complex(a)
211 def __complex__(a):
212 return complex(a.__num) / complex(a.__den)
213
214 # cmp(a,b)
215 def __cmp__(a, b):
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000216 diff = Rat(a - b)
Guido van Rossum0609f191997-05-13 19:25:57 +0000217 if diff.__num < 0:
218 return -1
219 elif diff.__num > 0:
220 return 1
221 else:
222 return 0
223
224 def __rcmp__(b, a):
225 return cmp(Rat(a), b)
226
227 # a != 0
228 def __nonzero__(a):
229 return a.__num != 0
230
231 # coercion
232 def __coerce__(a, b):
233 return a, Rat(b)
Guido van Rossume8769491992-08-13 12:14:11 +0000234
235def test():
Guido van Rossum0609f191997-05-13 19:25:57 +0000236 '''\
237 Test function for rat module.
238
239 The expected output is (module some differences in floating
240 precission):
241 -1
242 -1
243 0 0L 0.1 (0.1+0j)
244 [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
245 [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
246 0
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000247 (11/10)
248 (11/10)
Guido van Rossum0609f191997-05-13 19:25:57 +0000249 1.1
250 OK
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000251 2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
Guido van Rossum0609f191997-05-13 19:25:57 +0000252 2 2 2.0 (2+0j)
253
254 4 0 4 1 4 0
255 3.5 0.5 3.0 1.33333333333 2.82842712475 1
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000256 (7/2) (1/2) 3 (4/3) 2.82842712475 1
Guido van Rossum0609f191997-05-13 19:25:57 +0000257 (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
258 1.5 1 1.5 (1.5+0j)
259
260 3.5 -0.5 3.0 0.75 2.25 -1
261 3.0 0.0 2.25 1.0 1.83711730709 0
262 3.0 0.0 2.25 1.0 1.83711730709 1
263 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000264 (3/2) 1 1.5 (1.5+0j)
Guido van Rossum0609f191997-05-13 19:25:57 +0000265
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000266 (7/2) (-1/2) 3 (3/4) (9/4) -1
Guido van Rossum0609f191997-05-13 19:25:57 +0000267 3.0 0.0 2.25 1.0 1.83711730709 -1
Guido van Rossum7ca9a1a1998-09-09 14:07:06 +0000268 3 0 (9/4) 1 1.83711730709 0
Guido van Rossum0609f191997-05-13 19:25:57 +0000269 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
270 (1.5+1.5j) (1.5+1.5j)
271
272 (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
273 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
274 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
275 (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
276 '''
277 print rat(-1L, 1)
278 print rat(1, -1)
279 a = rat(1, 10)
280 print int(a), long(a), float(a), complex(a)
281 b = rat(2, 5)
Guido van Rossume8769491992-08-13 12:14:11 +0000282 l = [a+b, a-b, a*b, a/b]
283 print l
284 l.sort()
285 print l
Guido van Rossum0609f191997-05-13 19:25:57 +0000286 print rat(0, 1)
Guido van Rossume8769491992-08-13 12:14:11 +0000287 print a+1
288 print a+1L
289 print a+1.0
Guido van Rossumf1bbf9c1993-10-27 09:28:23 +0000290 try:
Guido van Rossum0609f191997-05-13 19:25:57 +0000291 print rat(1, 0)
Guido van Rossumf1bbf9c1993-10-27 09:28:23 +0000292 raise SystemError, 'should have been ZeroDivisionError'
293 except ZeroDivisionError:
294 print 'OK'
Guido van Rossum0609f191997-05-13 19:25:57 +0000295 print rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000)
296 list = [2, 1.5, rat(3,2), 1.5+1.5j]
297 for i in list:
298 print i,
299 if type(i) is not ComplexType:
300 print int(i), float(i),
301 print complex(i)
302 print
303 for j in list:
304 print i + j, i - j, i * j, i / j, i ** j, cmp(i, j)
Guido van Rossume8769491992-08-13 12:14:11 +0000305
Guido van Rossum0609f191997-05-13 19:25:57 +0000306if __name__ == '__main__':
307 test()