• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Tests for Lib/fractions.py."""
2
3from decimal import Decimal
4from test.support import requires_IEEE_754
5import math
6import numbers
7import operator
8import fractions
9import functools
10import sys
11import unittest
12import warnings
13from copy import copy, deepcopy
14from pickle import dumps, loads
15F = fractions.Fraction
16gcd = fractions.gcd
17
18class DummyFloat(object):
19    """Dummy float class for testing comparisons with Fractions"""
20
21    def __init__(self, value):
22        if not isinstance(value, float):
23            raise TypeError("DummyFloat can only be initialized from float")
24        self.value = value
25
26    def _richcmp(self, other, op):
27        if isinstance(other, numbers.Rational):
28            return op(F.from_float(self.value), other)
29        elif isinstance(other, DummyFloat):
30            return op(self.value, other.value)
31        else:
32            return NotImplemented
33
34    def __eq__(self, other): return self._richcmp(other, operator.eq)
35    def __le__(self, other): return self._richcmp(other, operator.le)
36    def __lt__(self, other): return self._richcmp(other, operator.lt)
37    def __ge__(self, other): return self._richcmp(other, operator.ge)
38    def __gt__(self, other): return self._richcmp(other, operator.gt)
39
40    # shouldn't be calling __float__ at all when doing comparisons
41    def __float__(self):
42        assert False, "__float__ should not be invoked for comparisons"
43
44    # same goes for subtraction
45    def __sub__(self, other):
46        assert False, "__sub__ should not be invoked for comparisons"
47    __rsub__ = __sub__
48
49
50class DummyRational(object):
51    """Test comparison of Fraction with a naive rational implementation."""
52
53    def __init__(self, num, den):
54        g = math.gcd(num, den)
55        self.num = num // g
56        self.den = den // g
57
58    def __eq__(self, other):
59        if isinstance(other, fractions.Fraction):
60            return (self.num == other._numerator and
61                    self.den == other._denominator)
62        else:
63            return NotImplemented
64
65    def __lt__(self, other):
66        return(self.num * other._denominator < self.den * other._numerator)
67
68    def __gt__(self, other):
69        return(self.num * other._denominator > self.den * other._numerator)
70
71    def __le__(self, other):
72        return(self.num * other._denominator <= self.den * other._numerator)
73
74    def __ge__(self, other):
75        return(self.num * other._denominator >= self.den * other._numerator)
76
77    # this class is for testing comparisons; conversion to float
78    # should never be used for a comparison, since it loses accuracy
79    def __float__(self):
80        assert False, "__float__ should not be invoked"
81
82class DummyFraction(fractions.Fraction):
83    """Dummy Fraction subclass for copy and deepcopy testing."""
84
85class GcdTest(unittest.TestCase):
86
87    def testMisc(self):
88        # fractions.gcd() is deprecated
89        with self.assertWarnsRegex(DeprecationWarning, r'fractions\.gcd'):
90            gcd(1, 1)
91        with warnings.catch_warnings():
92            warnings.filterwarnings('ignore', r'fractions\.gcd',
93                                    DeprecationWarning)
94            self.assertEqual(0, gcd(0, 0))
95            self.assertEqual(1, gcd(1, 0))
96            self.assertEqual(-1, gcd(-1, 0))
97            self.assertEqual(1, gcd(0, 1))
98            self.assertEqual(-1, gcd(0, -1))
99            self.assertEqual(1, gcd(7, 1))
100            self.assertEqual(-1, gcd(7, -1))
101            self.assertEqual(1, gcd(-23, 15))
102            self.assertEqual(12, gcd(120, 84))
103            self.assertEqual(-12, gcd(84, -120))
104            self.assertEqual(gcd(120.0, 84), 12.0)
105            self.assertEqual(gcd(120, 84.0), 12.0)
106            self.assertEqual(gcd(F(120), F(84)), F(12))
107            self.assertEqual(gcd(F(120, 77), F(84, 55)), F(12, 385))
108
109
110def _components(r):
111    return (r.numerator, r.denominator)
112
113
114class FractionTest(unittest.TestCase):
115
116    def assertTypedEquals(self, expected, actual):
117        """Asserts that both the types and values are the same."""
118        self.assertEqual(type(expected), type(actual))
119        self.assertEqual(expected, actual)
120
121    def assertTypedTupleEquals(self, expected, actual):
122        """Asserts that both the types and values in the tuples are the same."""
123        self.assertTupleEqual(expected, actual)
124        self.assertListEqual(list(map(type, expected)), list(map(type, actual)))
125
126    def assertRaisesMessage(self, exc_type, message,
127                            callable, *args, **kwargs):
128        """Asserts that callable(*args, **kwargs) raises exc_type(message)."""
129        try:
130            callable(*args, **kwargs)
131        except exc_type as e:
132            self.assertEqual(message, str(e))
133        else:
134            self.fail("%s not raised" % exc_type.__name__)
135
136    def testInit(self):
137        self.assertEqual((0, 1), _components(F()))
138        self.assertEqual((7, 1), _components(F(7)))
139        self.assertEqual((7, 3), _components(F(F(7, 3))))
140
141        self.assertEqual((-1, 1), _components(F(-1, 1)))
142        self.assertEqual((-1, 1), _components(F(1, -1)))
143        self.assertEqual((1, 1), _components(F(-2, -2)))
144        self.assertEqual((1, 2), _components(F(5, 10)))
145        self.assertEqual((7, 15), _components(F(7, 15)))
146        self.assertEqual((10**23, 1), _components(F(10**23)))
147
148        self.assertEqual((3, 77), _components(F(F(3, 7), 11)))
149        self.assertEqual((-9, 5), _components(F(2, F(-10, 9))))
150        self.assertEqual((2486, 2485), _components(F(F(22, 7), F(355, 113))))
151
152        self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
153                                 F, 12, 0)
154        self.assertRaises(TypeError, F, 1.5 + 3j)
155
156        self.assertRaises(TypeError, F, "3/2", 3)
157        self.assertRaises(TypeError, F, 3, 0j)
158        self.assertRaises(TypeError, F, 3, 1j)
159        self.assertRaises(TypeError, F, 1, 2, 3)
160
161    @requires_IEEE_754
162    def testInitFromFloat(self):
163        self.assertEqual((5, 2), _components(F(2.5)))
164        self.assertEqual((0, 1), _components(F(-0.0)))
165        self.assertEqual((3602879701896397, 36028797018963968),
166                         _components(F(0.1)))
167        # bug 16469: error types should be consistent with float -> int
168        self.assertRaises(ValueError, F, float('nan'))
169        self.assertRaises(OverflowError, F, float('inf'))
170        self.assertRaises(OverflowError, F, float('-inf'))
171
172    def testInitFromDecimal(self):
173        self.assertEqual((11, 10),
174                         _components(F(Decimal('1.1'))))
175        self.assertEqual((7, 200),
176                         _components(F(Decimal('3.5e-2'))))
177        self.assertEqual((0, 1),
178                         _components(F(Decimal('.000e20'))))
179        # bug 16469: error types should be consistent with decimal -> int
180        self.assertRaises(ValueError, F, Decimal('nan'))
181        self.assertRaises(ValueError, F, Decimal('snan'))
182        self.assertRaises(OverflowError, F, Decimal('inf'))
183        self.assertRaises(OverflowError, F, Decimal('-inf'))
184
185    def testFromString(self):
186        self.assertEqual((5, 1), _components(F("5")))
187        self.assertEqual((3, 2), _components(F("3/2")))
188        self.assertEqual((3, 2), _components(F(" \n  +3/2")))
189        self.assertEqual((-3, 2), _components(F("-3/2  ")))
190        self.assertEqual((13, 2), _components(F("    013/02 \n  ")))
191        self.assertEqual((16, 5), _components(F(" 3.2 ")))
192        self.assertEqual((-16, 5), _components(F(" -3.2 ")))
193        self.assertEqual((-3, 1), _components(F(" -3. ")))
194        self.assertEqual((3, 5), _components(F(" .6 ")))
195        self.assertEqual((1, 3125), _components(F("32.e-5")))
196        self.assertEqual((1000000, 1), _components(F("1E+06")))
197        self.assertEqual((-12300, 1), _components(F("-1.23e4")))
198        self.assertEqual((0, 1), _components(F(" .0e+0\t")))
199        self.assertEqual((0, 1), _components(F("-0.000e0")))
200
201        self.assertRaisesMessage(
202            ZeroDivisionError, "Fraction(3, 0)",
203            F, "3/0")
204        self.assertRaisesMessage(
205            ValueError, "Invalid literal for Fraction: '3/'",
206            F, "3/")
207        self.assertRaisesMessage(
208            ValueError, "Invalid literal for Fraction: '/2'",
209            F, "/2")
210        self.assertRaisesMessage(
211            ValueError, "Invalid literal for Fraction: '3 /2'",
212            F, "3 /2")
213        self.assertRaisesMessage(
214            # Denominators don't need a sign.
215            ValueError, "Invalid literal for Fraction: '3/+2'",
216            F, "3/+2")
217        self.assertRaisesMessage(
218            # Imitate float's parsing.
219            ValueError, "Invalid literal for Fraction: '+ 3/2'",
220            F, "+ 3/2")
221        self.assertRaisesMessage(
222            # Avoid treating '.' as a regex special character.
223            ValueError, "Invalid literal for Fraction: '3a2'",
224            F, "3a2")
225        self.assertRaisesMessage(
226            # Don't accept combinations of decimals and rationals.
227            ValueError, "Invalid literal for Fraction: '3/7.2'",
228            F, "3/7.2")
229        self.assertRaisesMessage(
230            # Don't accept combinations of decimals and rationals.
231            ValueError, "Invalid literal for Fraction: '3.2/7'",
232            F, "3.2/7")
233        self.assertRaisesMessage(
234            # Allow 3. and .3, but not .
235            ValueError, "Invalid literal for Fraction: '.'",
236            F, ".")
237
238    def testImmutable(self):
239        r = F(7, 3)
240        r.__init__(2, 15)
241        self.assertEqual((7, 3), _components(r))
242
243        self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
244        self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
245        self.assertEqual((7, 3), _components(r))
246
247        # But if you _really_ need to:
248        r._numerator = 4
249        r._denominator = 2
250        self.assertEqual((4, 2), _components(r))
251        # Which breaks some important operations:
252        self.assertNotEqual(F(4, 2), r)
253
254    def testFromFloat(self):
255        self.assertRaises(TypeError, F.from_float, 3+4j)
256        self.assertEqual((10, 1), _components(F.from_float(10)))
257        bigint = 1234567890123456789
258        self.assertEqual((bigint, 1), _components(F.from_float(bigint)))
259        self.assertEqual((0, 1), _components(F.from_float(-0.0)))
260        self.assertEqual((10, 1), _components(F.from_float(10.0)))
261        self.assertEqual((-5, 2), _components(F.from_float(-2.5)))
262        self.assertEqual((99999999999999991611392, 1),
263                         _components(F.from_float(1e23)))
264        self.assertEqual(float(10**23), float(F.from_float(1e23)))
265        self.assertEqual((3602879701896397, 1125899906842624),
266                         _components(F.from_float(3.2)))
267        self.assertEqual(3.2, float(F.from_float(3.2)))
268
269        inf = 1e1000
270        nan = inf - inf
271        # bug 16469: error types should be consistent with float -> int
272        self.assertRaisesMessage(
273            OverflowError, "cannot convert Infinity to integer ratio",
274            F.from_float, inf)
275        self.assertRaisesMessage(
276            OverflowError, "cannot convert Infinity to integer ratio",
277            F.from_float, -inf)
278        self.assertRaisesMessage(
279            ValueError, "cannot convert NaN to integer ratio",
280            F.from_float, nan)
281
282    def testFromDecimal(self):
283        self.assertRaises(TypeError, F.from_decimal, 3+4j)
284        self.assertEqual(F(10, 1), F.from_decimal(10))
285        self.assertEqual(F(0), F.from_decimal(Decimal("-0")))
286        self.assertEqual(F(5, 10), F.from_decimal(Decimal("0.5")))
287        self.assertEqual(F(5, 1000), F.from_decimal(Decimal("5e-3")))
288        self.assertEqual(F(5000), F.from_decimal(Decimal("5e3")))
289        self.assertEqual(1 - F(1, 10**30),
290                         F.from_decimal(Decimal("0." + "9" * 30)))
291
292        # bug 16469: error types should be consistent with decimal -> int
293        self.assertRaisesMessage(
294            OverflowError, "cannot convert Infinity to integer ratio",
295            F.from_decimal, Decimal("inf"))
296        self.assertRaisesMessage(
297            OverflowError, "cannot convert Infinity to integer ratio",
298            F.from_decimal, Decimal("-inf"))
299        self.assertRaisesMessage(
300            ValueError, "cannot convert NaN to integer ratio",
301            F.from_decimal, Decimal("nan"))
302        self.assertRaisesMessage(
303            ValueError, "cannot convert NaN to integer ratio",
304            F.from_decimal, Decimal("snan"))
305
306    def test_as_integer_ratio(self):
307        self.assertEqual(F(4, 6).as_integer_ratio(), (2, 3))
308        self.assertEqual(F(-4, 6).as_integer_ratio(), (-2, 3))
309        self.assertEqual(F(4, -6).as_integer_ratio(), (-2, 3))
310        self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1))
311
312    def testLimitDenominator(self):
313        rpi = F('3.1415926535897932')
314        self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
315        self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
316        self.assertEqual(rpi.limit_denominator(113), F(355, 113))
317        self.assertEqual(rpi.limit_denominator(112), F(333, 106))
318        self.assertEqual(F(201, 200).limit_denominator(100), F(1))
319        self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
320        self.assertEqual(F(0).limit_denominator(10000), F(0))
321        for i in (0, -1):
322            self.assertRaisesMessage(
323                ValueError, "max_denominator should be at least 1",
324                F(1).limit_denominator, i)
325
326    def testConversions(self):
327        self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
328        self.assertTypedEquals(1, math.trunc(F(11, 10)))
329        self.assertTypedEquals(-2, math.floor(F(-11, 10)))
330        self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
331        self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
332        self.assertTypedEquals(-1, int(F(-11, 10)))
333        self.assertTypedEquals(0, round(F(-1, 10)))
334        self.assertTypedEquals(0, round(F(-5, 10)))
335        self.assertTypedEquals(-2, round(F(-15, 10)))
336        self.assertTypedEquals(-1, round(F(-7, 10)))
337
338        self.assertEqual(False, bool(F(0, 1)))
339        self.assertEqual(True, bool(F(3, 2)))
340        self.assertTypedEquals(0.1, float(F(1, 10)))
341
342        # Check that __float__ isn't implemented by converting the
343        # numerator and denominator to float before dividing.
344        self.assertRaises(OverflowError, float, int('2'*400+'7'))
345        self.assertAlmostEqual(2.0/3,
346                               float(F(int('2'*400+'7'), int('3'*400+'1'))))
347
348        self.assertTypedEquals(0.1+0j, complex(F(1,10)))
349
350    def testBoolGuarateesBoolReturn(self):
351        # Ensure that __bool__ is used on numerator which guarantees a bool
352        # return.  See also bpo-39274.
353        @functools.total_ordering
354        class CustomValue:
355            denominator = 1
356
357            def __init__(self, value):
358                self.value = value
359
360            def __bool__(self):
361                return bool(self.value)
362
363            @property
364            def numerator(self):
365                # required to preserve `self` during instantiation
366                return self
367
368            def __eq__(self, other):
369                raise AssertionError("Avoid comparisons in Fraction.__bool__")
370
371            __lt__ = __eq__
372
373        # We did not implement all abstract methods, so register:
374        numbers.Rational.register(CustomValue)
375
376        numerator = CustomValue(1)
377        r = F(numerator)
378        # ensure the numerator was not lost during instantiation:
379        self.assertIs(r.numerator, numerator)
380        self.assertIs(bool(r), True)
381
382        numerator = CustomValue(0)
383        r = F(numerator)
384        self.assertIs(bool(r), False)
385
386    def testRound(self):
387        self.assertTypedEquals(F(-200), round(F(-150), -2))
388        self.assertTypedEquals(F(-200), round(F(-250), -2))
389        self.assertTypedEquals(F(30), round(F(26), -1))
390        self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
391        self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
392
393    def testArithmetic(self):
394        self.assertEqual(F(1, 2), F(1, 10) + F(2, 5))
395        self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5))
396        self.assertEqual(F(1, 25), F(1, 10) * F(2, 5))
397        self.assertEqual(F(1, 4), F(1, 10) / F(2, 5))
398        self.assertTypedEquals(2, F(9, 10) // F(2, 5))
399        self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
400        self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
401        self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
402        self.assertEqual((F(1), F(5, 6)), divmod(F(7, 3), F(3, 2)))
403        self.assertEqual((F(-2), F(2, 3)), divmod(F(-7, 3), F(3, 2)))
404        self.assertEqual(F(8, 27), F(2, 3) ** F(3))
405        self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
406        self.assertTypedEquals(2.0, F(4) ** F(1, 2))
407        self.assertEqual(F(1, 1), +F(1, 1))
408        z = pow(F(-1), F(1, 2))
409        self.assertAlmostEqual(z.real, 0)
410        self.assertEqual(z.imag, 1)
411        # Regression test for #27539.
412        p = F(-1, 2) ** 0
413        self.assertEqual(p, F(1, 1))
414        self.assertEqual(p.numerator, 1)
415        self.assertEqual(p.denominator, 1)
416        p = F(-1, 2) ** -1
417        self.assertEqual(p, F(-2, 1))
418        self.assertEqual(p.numerator, -2)
419        self.assertEqual(p.denominator, 1)
420        p = F(-1, 2) ** -2
421        self.assertEqual(p, F(4, 1))
422        self.assertEqual(p.numerator, 4)
423        self.assertEqual(p.denominator, 1)
424
425    def testLargeArithmetic(self):
426        self.assertTypedEquals(
427            F(10101010100808080808080808101010101010000000000000000,
428              1010101010101010101010101011111111101010101010101010101010101),
429            F(10**35+1, 10**27+1) % F(10**27+1, 10**35-1)
430        )
431        self.assertTypedEquals(
432            F(7, 1901475900342344102245054808064),
433            F(-2**100, 3) % F(5, 2**100)
434        )
435        self.assertTypedTupleEquals(
436            (9999999999999999,
437             F(10101010100808080808080808101010101010000000000000000,
438               1010101010101010101010101011111111101010101010101010101010101)),
439            divmod(F(10**35+1, 10**27+1), F(10**27+1, 10**35-1))
440        )
441        self.assertTypedEquals(
442            -2 ** 200 // 15,
443            F(-2**100, 3) // F(5, 2**100)
444        )
445        self.assertTypedEquals(
446            1,
447            F(5, 2**100) // F(3, 2**100)
448        )
449        self.assertTypedEquals(
450            (1, F(2, 2**100)),
451            divmod(F(5, 2**100), F(3, 2**100))
452        )
453        self.assertTypedTupleEquals(
454            (-2 ** 200 // 15,
455             F(7, 1901475900342344102245054808064)),
456            divmod(F(-2**100, 3), F(5, 2**100))
457        )
458
459    def testMixedArithmetic(self):
460        self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
461        self.assertTypedEquals(1.1, F(1, 10) + 1.0)
462        self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
463        self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
464        self.assertTypedEquals(1.1, 1.0 + F(1, 10))
465        self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
466
467        self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
468        self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
469        self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
470        self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
471        self.assertTypedEquals(0.9, 1.0 - F(1, 10))
472        self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
473
474        self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
475        self.assertTypedEquals(0.1, F(1, 10) * 1.0)
476        self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
477        self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
478        self.assertTypedEquals(0.1, 1.0 * F(1, 10))
479        self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
480
481        self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
482        self.assertTypedEquals(0.1, F(1, 10) / 1.0)
483        self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
484        self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
485        self.assertTypedEquals(10.0, 1.0 / F(1, 10))
486        self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
487
488        self.assertTypedEquals(0, F(1, 10) // 1)
489        self.assertTypedEquals(0.0, F(1, 10) // 1.0)
490        self.assertTypedEquals(10, 1 // F(1, 10))
491        self.assertTypedEquals(10**23, 10**22 // F(1, 10))
492        self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
493
494        self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
495        self.assertTypedEquals(0.1, F(1, 10) % 1.0)
496        self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
497        self.assertTypedEquals(1.0 % 0.1, 1.0 % F(1, 10))
498        self.assertTypedEquals(0.1, F(1, 10) % float('inf'))
499        self.assertTypedEquals(float('-inf'), F(1, 10) % float('-inf'))
500        self.assertTypedEquals(float('inf'), F(-1, 10) % float('inf'))
501        self.assertTypedEquals(-0.1, F(-1, 10) % float('-inf'))
502
503        self.assertTypedTupleEquals((0, F(1, 10)), divmod(F(1, 10), 1))
504        self.assertTypedTupleEquals(divmod(0.1, 1.0), divmod(F(1, 10), 1.0))
505        self.assertTypedTupleEquals((10, F(0)), divmod(1, F(1, 10)))
506        self.assertTypedTupleEquals(divmod(1.0, 0.1), divmod(1.0, F(1, 10)))
507        self.assertTypedTupleEquals(divmod(0.1, float('inf')), divmod(F(1, 10), float('inf')))
508        self.assertTypedTupleEquals(divmod(0.1, float('-inf')), divmod(F(1, 10), float('-inf')))
509        self.assertTypedTupleEquals(divmod(-0.1, float('inf')), divmod(F(-1, 10), float('inf')))
510        self.assertTypedTupleEquals(divmod(-0.1, float('-inf')), divmod(F(-1, 10), float('-inf')))
511
512        # ** has more interesting conversion rules.
513        self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
514        self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
515        self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
516        self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
517        self.assertTypedEquals(4 , 2 ** F(2, 1))
518        z = pow(-1, F(1, 2))
519        self.assertAlmostEqual(0, z.real)
520        self.assertEqual(1, z.imag)
521        self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
522        self.assertTypedEquals(2.0 , 4 ** F(1, 2))
523        self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
524        self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
525        self.assertRaises(ZeroDivisionError, operator.pow,
526                          F(0, 1), -2)
527
528    def testMixingWithDecimal(self):
529        # Decimal refuses mixed arithmetic (but not mixed comparisons)
530        self.assertRaises(TypeError, operator.add,
531                          F(3,11), Decimal('3.1415926'))
532        self.assertRaises(TypeError, operator.add,
533                          Decimal('3.1415926'), F(3,11))
534
535    def testComparisons(self):
536        self.assertTrue(F(1, 2) < F(2, 3))
537        self.assertFalse(F(1, 2) < F(1, 2))
538        self.assertTrue(F(1, 2) <= F(2, 3))
539        self.assertTrue(F(1, 2) <= F(1, 2))
540        self.assertFalse(F(2, 3) <= F(1, 2))
541        self.assertTrue(F(1, 2) == F(1, 2))
542        self.assertFalse(F(1, 2) == F(1, 3))
543        self.assertFalse(F(1, 2) != F(1, 2))
544        self.assertTrue(F(1, 2) != F(1, 3))
545
546    def testComparisonsDummyRational(self):
547        self.assertTrue(F(1, 2) == DummyRational(1, 2))
548        self.assertTrue(DummyRational(1, 2) == F(1, 2))
549        self.assertFalse(F(1, 2) == DummyRational(3, 4))
550        self.assertFalse(DummyRational(3, 4) == F(1, 2))
551
552        self.assertTrue(F(1, 2) < DummyRational(3, 4))
553        self.assertFalse(F(1, 2) < DummyRational(1, 2))
554        self.assertFalse(F(1, 2) < DummyRational(1, 7))
555        self.assertFalse(F(1, 2) > DummyRational(3, 4))
556        self.assertFalse(F(1, 2) > DummyRational(1, 2))
557        self.assertTrue(F(1, 2) > DummyRational(1, 7))
558        self.assertTrue(F(1, 2) <= DummyRational(3, 4))
559        self.assertTrue(F(1, 2) <= DummyRational(1, 2))
560        self.assertFalse(F(1, 2) <= DummyRational(1, 7))
561        self.assertFalse(F(1, 2) >= DummyRational(3, 4))
562        self.assertTrue(F(1, 2) >= DummyRational(1, 2))
563        self.assertTrue(F(1, 2) >= DummyRational(1, 7))
564
565        self.assertTrue(DummyRational(1, 2) < F(3, 4))
566        self.assertFalse(DummyRational(1, 2) < F(1, 2))
567        self.assertFalse(DummyRational(1, 2) < F(1, 7))
568        self.assertFalse(DummyRational(1, 2) > F(3, 4))
569        self.assertFalse(DummyRational(1, 2) > F(1, 2))
570        self.assertTrue(DummyRational(1, 2) > F(1, 7))
571        self.assertTrue(DummyRational(1, 2) <= F(3, 4))
572        self.assertTrue(DummyRational(1, 2) <= F(1, 2))
573        self.assertFalse(DummyRational(1, 2) <= F(1, 7))
574        self.assertFalse(DummyRational(1, 2) >= F(3, 4))
575        self.assertTrue(DummyRational(1, 2) >= F(1, 2))
576        self.assertTrue(DummyRational(1, 2) >= F(1, 7))
577
578    def testComparisonsDummyFloat(self):
579        x = DummyFloat(1./3.)
580        y = F(1, 3)
581        self.assertTrue(x != y)
582        self.assertTrue(x < y or x > y)
583        self.assertFalse(x == y)
584        self.assertFalse(x <= y and x >= y)
585        self.assertTrue(y != x)
586        self.assertTrue(y < x or y > x)
587        self.assertFalse(y == x)
588        self.assertFalse(y <= x and y >= x)
589
590    def testMixedLess(self):
591        self.assertTrue(2 < F(5, 2))
592        self.assertFalse(2 < F(4, 2))
593        self.assertTrue(F(5, 2) < 3)
594        self.assertFalse(F(4, 2) < 2)
595
596        self.assertTrue(F(1, 2) < 0.6)
597        self.assertFalse(F(1, 2) < 0.4)
598        self.assertTrue(0.4 < F(1, 2))
599        self.assertFalse(0.5 < F(1, 2))
600
601        self.assertFalse(float('inf') < F(1, 2))
602        self.assertTrue(float('-inf') < F(0, 10))
603        self.assertFalse(float('nan') < F(-3, 7))
604        self.assertTrue(F(1, 2) < float('inf'))
605        self.assertFalse(F(17, 12) < float('-inf'))
606        self.assertFalse(F(144, -89) < float('nan'))
607
608    def testMixedLessEqual(self):
609        self.assertTrue(0.5 <= F(1, 2))
610        self.assertFalse(0.6 <= F(1, 2))
611        self.assertTrue(F(1, 2) <= 0.5)
612        self.assertFalse(F(1, 2) <= 0.4)
613        self.assertTrue(2 <= F(4, 2))
614        self.assertFalse(2 <= F(3, 2))
615        self.assertTrue(F(4, 2) <= 2)
616        self.assertFalse(F(5, 2) <= 2)
617
618        self.assertFalse(float('inf') <= F(1, 2))
619        self.assertTrue(float('-inf') <= F(0, 10))
620        self.assertFalse(float('nan') <= F(-3, 7))
621        self.assertTrue(F(1, 2) <= float('inf'))
622        self.assertFalse(F(17, 12) <= float('-inf'))
623        self.assertFalse(F(144, -89) <= float('nan'))
624
625    def testBigFloatComparisons(self):
626        # Because 10**23 can't be represented exactly as a float:
627        self.assertFalse(F(10**23) == float(10**23))
628        # The first test demonstrates why these are important.
629        self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
630        self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
631        self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
632        self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
633        self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
634
635    def testBigComplexComparisons(self):
636        self.assertFalse(F(10**23) == complex(10**23))
637        self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23))
638        self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23))
639
640        x = F(3, 8)
641        z = complex(0.375, 0.0)
642        w = complex(0.375, 0.2)
643        self.assertTrue(x == z)
644        self.assertFalse(x != z)
645        self.assertFalse(x == w)
646        self.assertTrue(x != w)
647        for op in operator.lt, operator.le, operator.gt, operator.ge:
648            self.assertRaises(TypeError, op, x, z)
649            self.assertRaises(TypeError, op, z, x)
650            self.assertRaises(TypeError, op, x, w)
651            self.assertRaises(TypeError, op, w, x)
652
653    def testMixedEqual(self):
654        self.assertTrue(0.5 == F(1, 2))
655        self.assertFalse(0.6 == F(1, 2))
656        self.assertTrue(F(1, 2) == 0.5)
657        self.assertFalse(F(1, 2) == 0.4)
658        self.assertTrue(2 == F(4, 2))
659        self.assertFalse(2 == F(3, 2))
660        self.assertTrue(F(4, 2) == 2)
661        self.assertFalse(F(5, 2) == 2)
662        self.assertFalse(F(5, 2) == float('nan'))
663        self.assertFalse(float('nan') == F(3, 7))
664        self.assertFalse(F(5, 2) == float('inf'))
665        self.assertFalse(float('-inf') == F(2, 5))
666
667    def testStringification(self):
668        self.assertEqual("Fraction(7, 3)", repr(F(7, 3)))
669        self.assertEqual("Fraction(6283185307, 2000000000)",
670                         repr(F('3.1415926535')))
671        self.assertEqual("Fraction(-1, 100000000000000000000)",
672                         repr(F(1, -10**20)))
673        self.assertEqual("7/3", str(F(7, 3)))
674        self.assertEqual("7", str(F(7, 1)))
675
676    def testHash(self):
677        hmod = sys.hash_info.modulus
678        hinf = sys.hash_info.inf
679        self.assertEqual(hash(2.5), hash(F(5, 2)))
680        self.assertEqual(hash(10**50), hash(F(10**50)))
681        self.assertNotEqual(hash(float(10**23)), hash(F(10**23)))
682        self.assertEqual(hinf, hash(F(1, hmod)))
683        # Check that __hash__ produces the same value as hash(), for
684        # consistency with int and Decimal.  (See issue #10356.)
685        self.assertEqual(hash(F(-1)), F(-1).__hash__())
686
687    def testApproximatePi(self):
688        # Algorithm borrowed from
689        # http://docs.python.org/lib/decimal-recipes.html
690        three = F(3)
691        lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
692        while abs(s - lasts) > F(1, 10**9):
693            lasts = s
694            n, na = n+na, na+8
695            d, da = d+da, da+32
696            t = (t * n) / d
697            s += t
698        self.assertAlmostEqual(math.pi, s)
699
700    def testApproximateCos1(self):
701        # Algorithm borrowed from
702        # http://docs.python.org/lib/decimal-recipes.html
703        x = F(1)
704        i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
705        while abs(s - lasts) > F(1, 10**9):
706            lasts = s
707            i += 2
708            fact *= i * (i-1)
709            num *= x * x
710            sign *= -1
711            s += num / fact * sign
712        self.assertAlmostEqual(math.cos(1), s)
713
714    def test_copy_deepcopy_pickle(self):
715        r = F(13, 7)
716        dr = DummyFraction(13, 7)
717        self.assertEqual(r, loads(dumps(r)))
718        self.assertEqual(id(r), id(copy(r)))
719        self.assertEqual(id(r), id(deepcopy(r)))
720        self.assertNotEqual(id(dr), id(copy(dr)))
721        self.assertNotEqual(id(dr), id(deepcopy(dr)))
722        self.assertTypedEquals(dr, copy(dr))
723        self.assertTypedEquals(dr, deepcopy(dr))
724
725    def test_slots(self):
726        # Issue 4998
727        r = F(13, 7)
728        self.assertRaises(AttributeError, setattr, r, 'a', 10)
729
730if __name__ == '__main__':
731    unittest.main()
732