Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0609f19

Browse files
committed
A completely new Rat.py by Sjoerd.
1 parent e0332c7 commit 0609f19

1 file changed

Lines changed: 260 additions & 56 deletions

File tree

Demo/classes/Rat.py

Lines changed: 260 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,307 @@
1-
# Rational numbers
1+
'''\
2+
This module implements rational numbers.
23
3-
from types import *
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.
412
5-
def rat(num, den):
6-
if type(num) == FloatType or type(den) == FloatType:
7-
return num/den
8-
return Rat(num, den)
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+
'''
918

19+
# Contributed by Sjoerd Mullender
20+
21+
from types import *
1022

1123
def gcd(a, b):
24+
'''Calculate the Greatest Common Divisor.'''
1225
while b:
1326
a, b = b, a%b
1427
return a
1528

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)
1639

1740
class Rat:
41+
'''This class implements rational numbers.'''
1842

19-
def __init__(self, num, den):
43+
def __init__(self, num, den = 1):
2044
if den == 0:
2145
raise ZeroDivisionError, 'rat(x, 0)'
22-
if type(den) == FloatType or type(num) == FloatType:
23-
g = float(den)
46+
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
2478
else:
79+
# make sure numerator and denominator don't
80+
# have common factors
81+
# this also makes sure that denominator > 0
2582
g = gcd(num, den)
26-
self.num = num/g
27-
self.den = den/g
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
2895

2996
def __repr__(self):
30-
return 'Rat(%s, %s)' % (self.num, self.den)
97+
return 'Rat(%s,%s)' % (self.__num, self.__den)
3198

3299
def __str__(self):
33-
if self.den == 1:
34-
return str(self.num)
100+
if self.__den == 1:
101+
return str(self.__num)
35102
else:
36-
return '%s/%s' % (self.num, self.den)
103+
return '%s/%s' % (str(self.__num), str(self.__den))
104+
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))
114+
115+
def __radd__(b, a):
116+
return Rat(a) + b
117+
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))
127+
128+
def __rsub__(b, a):
129+
return Rat(a) - b
130+
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))
138+
139+
def __rmul__(b, a):
140+
return Rat(a) * b
141+
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))
149+
150+
def __rdiv__(b, a):
151+
return Rat(a) / b
37152

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
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)
38215
def __cmp__(a, b):
39-
c = a-b
40-
if c.num < 0:
216+
diff = a - b
217+
if diff.__num < 0:
41218
return -1
42-
if c.num > 0:
219+
elif diff.__num > 0:
43220
return 1
44-
return 0
45-
46-
def __float__(self):
47-
return float(self.num) / float(self.den)
221+
else:
222+
return 0
48223

49-
def __long__(self):
50-
return long(self.num) / long(self.den)
224+
def __rcmp__(b, a):
225+
return cmp(Rat(a), b)
51226

52-
def __int__(self):
53-
return int(self.num / self.den)
227+
# a != 0
228+
def __nonzero__(a):
229+
return a.__num != 0
54230

231+
# coercion
55232
def __coerce__(a, b):
56-
t = type(b)
57-
if t == IntType:
58-
return a, Rat(b, 1)
59-
if t == LongType:
60-
return a, Rat(b, 1L)
61-
if t == FloatType:
62-
return a, Rat(b, 1.0)
63-
if t == InstanceType and a.__class__ == b.__class__:
64-
return a, b
65-
raise TypeError, 'Rat.__coerce__: bad other arg'
233+
return a, Rat(b)
66234

67-
def __add__(a, b):
68-
return rat(a.num*b.den + b.num*a.den, a.den*b.den)
69-
70-
def __sub__(a, b):
71-
return rat(a.num*b.den - b.num*a.den, a.den*b.den)
235+
def test():
236+
'''\
237+
Test function for rat module.
72238
73-
def __mul__(a, b):
74-
return rat(a.num*b.num, a.den*b.den)
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
247+
11/10
248+
11/10
249+
1.1
250+
OK
251+
2 1.5 3/2 (1.5+1.5j) 15707963/5000000
252+
2 2 2.0 (2+0j)
75253
76-
def __div__(a, b):
77-
return rat(a.num*b.den, a.den*b.num)
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)
78259
79-
def __neg__(self):
80-
return rat(-self.num, self.den)
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)
81265
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)
82271
83-
def test():
84-
print Rat(-1L, 1)
85-
print Rat(1, -1)
86-
a = Rat(1, 10)
87-
print int(a), long(a), float(a)
88-
b = Rat(2, 5)
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)
89282
l = [a+b, a-b, a*b, a/b]
90283
print l
91284
l.sort()
92285
print l
93-
print Rat(0, 1)
286+
print rat(0, 1)
94287
print a+1
95288
print a+1L
96289
print a+1.0
97290
try:
98-
print Rat(1, 0)
291+
print rat(1, 0)
99292
raise SystemError, 'should have been ZeroDivisionError'
100293
except ZeroDivisionError:
101294
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)
102305

103-
test()
306+
if __name__ == '__main__':
307+
test()

0 commit comments

Comments
 (0)