Move setting of ioready 'wait' earlier in call chain, to
[python/dscho.git] / Demo / classes / Rat.py
blob4fc4a1786f1f447c272d884598d2b0c65c21a1b2
1 '''\
2 This module implements rational numbers.
4 The entry point of this module is the function
5 rat(numerator, denominator)
6 If either numerator or denominator is of an integral or rational type,
7 the result is a rational number, else, the result is the simplest of
8 the types float and complex which can hold numerator/denominator.
9 If denominator is omitted, it defaults to 1.
10 Rational numbers can be used in calculations with any other numeric
11 type. The result of the calculation will be rational if possible.
13 There is also a test function with calling sequence
14 test()
15 The documentation string of the test function contains the expected
16 output.
17 '''
19 # Contributed by Sjoerd Mullender
21 from types import *
23 def gcd(a, b):
24 '''Calculate the Greatest Common Divisor.'''
25 while b:
26 a, b = b, a%b
27 return a
29 def 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)
40 class Rat:
41 '''This class implements rational numbers.'''
43 def __init__(self, num, den = 1):
44 if den == 0:
45 raise ZeroDivisionError, 'rat(x, 0)'
47 # normalize
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
78 else:
79 # make sure numerator and denominator don't
80 # have common factors
81 # this also makes sure that denominator > 0
82 g = gcd(num, den)
83 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
96 def __repr__(self):
97 return 'Rat(%s,%s)' % (self.__num, self.__den)
99 def __str__(self):
100 if self.__den == 1:
101 return str(self.__num)
102 else:
103 return '(%s/%s)' % (str(self.__num), str(self.__den))
105 # a + b
106 def __add__(a, b):
107 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))
115 def __radd__(b, a):
116 return Rat(a) + b
118 # a - b
119 def __sub__(a, b):
120 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))
128 def __rsub__(b, a):
129 return Rat(a) - b
131 # a * b
132 def __mul__(a, b):
133 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))
139 def __rmul__(b, a):
140 return Rat(a) * b
142 # a / b
143 def __div__(a, b):
144 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))
150 def __rdiv__(b, a):
151 return Rat(a) / b
153 # 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
162 def __rmod__(b, a):
163 return Rat(a) % b
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)
183 def __rpow__(b, a):
184 return Rat(a) ** b
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)
194 # abs(a)
195 def __abs__(a):
196 return rat(abs(a.__num), a.__den)
198 # int(a)
199 def __int__(a):
200 return int(a.__num / a.__den)
202 # long(a)
203 def __long__(a):
204 return long(a.__num) / long(a.__den)
206 # float(a)
207 def __float__(a):
208 return float(a.__num) / float(a.__den)
210 # complex(a)
211 def __complex__(a):
212 return complex(a.__num) / complex(a.__den)
214 # cmp(a,b)
215 def __cmp__(a, b):
216 diff = Rat(a - b)
217 if diff.__num < 0:
218 return -1
219 elif diff.__num > 0:
220 return 1
221 else:
222 return 0
224 def __rcmp__(b, a):
225 return cmp(Rat(a), b)
227 # a != 0
228 def __nonzero__(a):
229 return a.__num != 0
231 # coercion
232 def __coerce__(a, b):
233 return a, Rat(b)
235 def test():
236 '''\
237 Test function for rat module.
239 The expected output is (module some differences in floating
240 precission):
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)]
247 (11/10)
248 (11/10)
251 2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
252 2 2 2.0 (2+0j)
254 4 0 4 1 4 0
255 3.5 0.5 3.0 1.33333333333 2.82842712475 1
256 (7/2) (1/2) 3 (4/3) 2.82842712475 1
257 (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)
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
264 (3/2) 1 1.5 (1.5+0j)
266 (7/2) (-1/2) 3 (3/4) (9/4) -1
267 3.0 0.0 2.25 1.0 1.83711730709 -1
268 3 0 (9/4) 1 1.83711730709 0
269 (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)
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
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)
282 l = [a+b, a-b, a*b, a/b]
283 print l
284 l.sort()
285 print l
286 print rat(0, 1)
287 print a+1
288 print a+1L
289 print a+1.0
290 try:
291 print rat(1, 0)
292 raise SystemError, 'should have been ZeroDivisionError'
293 except ZeroDivisionError:
294 print 'OK'
295 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)
306 if __name__ == '__main__':
307 test()