1 """Tests for binary operators on subtypes of built-in types."""
4 from test
import test_support
7 """Greatest common divisor using Euclid's algorithm."""
13 """Test whether an object is an instance of int or long."""
14 return isinstance(x
, int) or isinstance(x
, long)
17 """Test whether an object is an instance of a built-in numeric type."""
18 for T
in int, long, float, complex:
24 """Test wheter an object is an instance of the Rat class."""
25 return isinstance(x
, Rat
)
29 """Rational number implemented as a normalized pair of longs."""
31 __slots__
= ['_Rat__num', '_Rat__den']
33 def __init__(self
, num
=0L, den
=1L):
34 """Constructor: Rat([num[, den]]).
36 The arguments must be ints or longs, and default to (0, 1)."""
38 raise TypeError, "Rat numerator must be int or long (%r)" % num
40 raise TypeError, "Rat denominator must be int or long (%r)" % den
41 # But the zero is always on
43 raise ZeroDivisionError, "zero denominator"
45 self
.__num
= long(num
//g
)
46 self
.__den
= long(den
//g
)
49 """Accessor function for read-only 'num' attribute of Rat."""
51 num
= property(_get_num
, None)
54 """Accessor function for read-only 'den' attribute of Rat."""
56 den
= property(_get_den
, None)
59 """Convert a Rat to an string resembling a Rat constructor call."""
60 return "Rat(%d, %d)" % (self
.__num
, self
.__den
)
63 """Convert a Rat to a string resembling a decimal numeric value."""
64 return str(float(self
))
67 """Convert a Rat to a float."""
68 return self
.__num
*1.0/self
.__den
71 """Convert a Rat to an int; self.den must be 1."""
74 return int(self
.__num
)
76 raise OverflowError, ("%s too large to convert to int" %
78 raise ValueError, "can't convert %s to int" % repr(self
)
81 """Convert a Rat to an long; self.den must be 1."""
83 return long(self
.__num
)
84 raise ValueError, "can't convert %s to long" % repr(self
)
86 def __add__(self
, other
):
87 """Add two Rats, or a Rat and a number."""
91 return Rat(self
.__num
*other
.__den
+ other
.__num
*self
.__den
,
92 self
.__den
*other
.__den
)
94 return float(self
) + other
99 def __sub__(self
, other
):
100 """Subtract two Rats, or a Rat and a number."""
104 return Rat(self
.__num
*other
.__den
- other
.__num
*self
.__den
,
105 self
.__den
*other
.__den
)
107 return float(self
) - other
108 return NotImplemented
110 def __rsub__(self
, other
):
111 """Subtract two Rats, or a Rat and a number (reversed args)."""
115 return Rat(other
.__num
*self
.__den
- self
.__num
*other
.__den
,
116 self
.__den
*other
.__den
)
118 return other
- float(self
)
119 return NotImplemented
121 def __mul__(self
, other
):
122 """Multiply two Rats, or a Rat and a number."""
124 return Rat(self
.__num
*other
.__num
, self
.__den
*other
.__den
)
126 return Rat(self
.__num
*other
, self
.__den
)
128 return float(self
)*other
129 return NotImplemented
133 def __truediv__(self
, other
):
134 """Divide two Rats, or a Rat and a number."""
136 return Rat(self
.__num
*other
.__den
, self
.__den
*other
.__num
)
138 return Rat(self
.__num
, self
.__den
*other
)
140 return float(self
) / other
141 return NotImplemented
143 __div__
= __truediv__
145 def __rtruediv__(self
, other
):
146 """Divide two Rats, or a Rat and a number (reversed args)."""
148 return Rat(other
.__num
*self
.__den
, other
.__den
*self
.__num
)
150 return Rat(other
*self
.__den
, self
.__num
)
152 return other
/ float(self
)
153 return NotImplemented
155 __rdiv__
= __rtruediv__
157 def __floordiv__(self
, other
):
158 """Divide two Rats, returning the floored result."""
161 elif not isRat(other
):
162 return NotImplemented
164 return x
.__num
// x
.__den
166 def __rfloordiv__(self
, other
):
167 """Divide two Rats, returning the floored result (reversed args)."""
169 return x
.__num
// x
.__den
171 def __divmod__(self
, other
):
172 """Divide two Rats, returning quotient and remainder."""
175 elif not isRat(other
):
176 return NotImplemented
178 return (x
, self
- other
* x
)
180 def __rdivmod__(self
, other
):
181 """Divide two Rats, returning quotient and remainder (reversed args)."""
184 elif not isRat(other
):
185 return NotImplemented
186 return divmod(other
, self
)
188 def __mod__(self
, other
):
189 """Take one Rat modulo another."""
190 return divmod(self
, other
)[1]
192 def __rmod__(self
, other
):
193 """Take one Rat modulo another (reversed args)."""
194 return divmod(other
, self
)[1]
196 def __eq__(self
, other
):
197 """Compare two Rats for equality."""
199 return self
.__den
== 1 and self
.__num
== other
201 return self
.__num
== other
.__num
and self
.__den
== other
.__den
203 return float(self
) == other
204 return NotImplemented
206 def __ne__(self
, other
):
207 """Compare two Rats for inequality."""
208 return not self
== other
210 class RatTestCase(unittest
.TestCase
):
211 """Unit tests for Rat class and its support utilities."""
214 self
.assertEqual(gcd(10, 12), 2)
215 self
.assertEqual(gcd(10, 15), 5)
216 self
.assertEqual(gcd(10, 11), 1)
217 self
.assertEqual(gcd(100, 15), 5)
218 self
.assertEqual(gcd(-10, 2), -2)
219 self
.assertEqual(gcd(10, -2), 2)
220 self
.assertEqual(gcd(-10, -2), -2)
221 for i
in range(1, 20):
222 for j
in range(1, 20):
223 self
.assert_(gcd(i
, j
) > 0)
224 self
.assert_(gcd(-i
, j
) < 0)
225 self
.assert_(gcd(i
, -j
) > 0)
226 self
.assert_(gcd(-i
, -j
) < 0)
228 def test_constructor(self
):
230 self
.assertEqual(a
.num
, 2)
231 self
.assertEqual(a
.den
, 3)
233 self
.assertEqual(a
.num
, 2)
234 self
.assertEqual(a
.den
, 3)
236 self
.assertEqual(a
.num
, -2)
237 self
.assertEqual(a
.den
, 3)
239 self
.assertEqual(a
.num
, -2)
240 self
.assertEqual(a
.den
, 3)
242 self
.assertEqual(a
.num
, 2)
243 self
.assertEqual(a
.den
, 3)
245 self
.assertEqual(a
.num
, 7)
246 self
.assertEqual(a
.den
, 1)
249 except ZeroDivisionError:
252 self
.fail("Rat(1, 0) didn't raise ZeroDivisionError")
253 for bad
in "0", 0.0, 0j
, (), [], {}, None, Rat
, unittest
:
259 self
.fail("Rat(%r) didn't raise TypeError" % bad
)
265 self
.fail("Rat(1, %r) didn't raise TypeError" % bad
)
268 self
.assertEqual(Rat(2, 3) + Rat(1, 3), 1)
269 self
.assertEqual(Rat(2, 3) + 1, Rat(5, 3))
270 self
.assertEqual(1 + Rat(2, 3), Rat(5, 3))
271 self
.assertEqual(1.0 + Rat(1, 2), 1.5)
272 self
.assertEqual(Rat(1, 2) + 1.0, 1.5)
275 self
.assertEqual(Rat(7, 2) - Rat(7, 5), Rat(21, 10))
276 self
.assertEqual(Rat(7, 5) - 1, Rat(2, 5))
277 self
.assertEqual(1 - Rat(3, 5), Rat(2, 5))
278 self
.assertEqual(Rat(3, 2) - 1.0, 0.5)
279 self
.assertEqual(1.0 - Rat(1, 2), 0.5)
282 self
.assertEqual(Rat(2, 3) * Rat(5, 7), Rat(10, 21))
283 self
.assertEqual(Rat(10, 3) * 3, 10)
284 self
.assertEqual(3 * Rat(10, 3), 10)
285 self
.assertEqual(Rat(10, 5) * 0.5, 1.0)
286 self
.assertEqual(0.5 * Rat(10, 5), 1.0)
289 self
.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3))
290 self
.assertEqual(Rat(10, 3) / 3, Rat(10, 9))
291 self
.assertEqual(2 / Rat(5), Rat(2, 5))
292 self
.assertEqual(3.0 * Rat(1, 2), 1.5)
293 self
.assertEqual(Rat(1, 2) * 3.0, 1.5)
295 def test_floordiv(self
):
296 self
.assertEqual(Rat(10) // Rat(4), 2)
297 self
.assertEqual(Rat(10, 3) // Rat(4, 3), 2)
298 self
.assertEqual(Rat(10) // 4, 2)
299 self
.assertEqual(10 // Rat(4), 2)
302 self
.assertEqual(Rat(10), Rat(20, 2))
303 self
.assertEqual(Rat(10), 10)
304 self
.assertEqual(10, Rat(10))
305 self
.assertEqual(Rat(10), 10.0)
306 self
.assertEqual(10.0, Rat(10))
308 def test_future_div(self
):
311 # XXX Ran out of steam; TO DO: divmod, div, future division
314 from __future__ import division
315 self.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3))
316 self.assertEqual(Rat(10, 3) / 3, Rat(10, 9))
317 self.assertEqual(2 / Rat(5), Rat(2, 5))
318 self.assertEqual(3.0 * Rat(1, 2), 1.5)
319 self.assertEqual(Rat(1, 2) * 3.0, 1.5)
320 self.assertEqual(eval('1/2'), 0.5)
324 test_support
.run_unittest(RatTestCase
)
327 if __name__
== "__main__":