blob: 86b49f30f549fb6a3ea1c7ce27fc31f685faf205 [file] [log] [blame]
Christian Heimes3feef612008-02-11 06:19:17 +00001"""Tests for Lib/fractions.py."""
Guido van Rossum7736b5b2008-01-15 21:44:53 +00002
3from decimal import Decimal
Zachary Ware38c707e2015-04-13 15:00:43 -05004from test.support import requires_IEEE_754
Guido van Rossum7736b5b2008-01-15 21:44:53 +00005import math
Mark Dickinson85424c92009-07-18 14:41:42 +00006import numbers
Guido van Rossum7736b5b2008-01-15 21:44:53 +00007import operator
Christian Heimes3feef612008-02-11 06:19:17 +00008import fractions
Miss Islington (bot)0d03a102020-02-06 07:13:38 -08009import functools
Ezio Melotti682d3742012-02-29 14:05:53 +020010import sys
Guido van Rossum7736b5b2008-01-15 21:44:53 +000011import unittest
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030012import warnings
Christian Heimes969fe572008-01-25 11:23:10 +000013from copy import copy, deepcopy
Neal Norwitz6ff93fe2008-01-26 21:52:30 +000014from pickle import dumps, loads
Christian Heimes68f5fbe2008-02-14 08:27:37 +000015F = fractions.Fraction
Christian Heimes3feef612008-02-11 06:19:17 +000016gcd = fractions.gcd
Christian Heimesaf98da12008-01-27 15:18:18 +000017
Mark Dickinson85424c92009-07-18 14:41:42 +000018class 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):
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030054 g = math.gcd(num, den)
Mark Dickinson85424c92009-07-18 14:41:42 +000055 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"
Christian Heimesaf98da12008-01-27 15:18:18 +000081
Ezio Melotti682d3742012-02-29 14:05:53 +020082class DummyFraction(fractions.Fraction):
83 """Dummy Fraction subclass for copy and deepcopy testing."""
84
Christian Heimesaf98da12008-01-27 15:18:18 +000085class GcdTest(unittest.TestCase):
86
87 def testMisc(self):
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030088 # 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))
Christian Heimesaf98da12008-01-27 15:18:18 +0000108
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000109
110def _components(r):
111 return (r.numerator, r.denominator)
112
Christian Heimesaf98da12008-01-27 15:18:18 +0000113
Christian Heimes3feef612008-02-11 06:19:17 +0000114class FractionTest(unittest.TestCase):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000115
116 def assertTypedEquals(self, expected, actual):
117 """Asserts that both the types and values are the same."""
Ezio Melottib3aedd42010-11-20 19:04:17 +0000118 self.assertEqual(type(expected), type(actual))
119 self.assertEqual(expected, actual)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000120
Stefan Behnel3a374e02019-01-02 13:22:06 +0100121 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000126 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:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000132 self.assertEqual(message, str(e))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000133 else:
134 self.fail("%s not raised" % exc_type.__name__)
135
136 def testInit(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000137 self.assertEqual((0, 1), _components(F()))
138 self.assertEqual((7, 1), _components(F(7)))
139 self.assertEqual((7, 3), _components(F(F(7, 3))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000140
Ezio Melottib3aedd42010-11-20 19:04:17 +0000141 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000147
Ezio Melottib3aedd42010-11-20 19:04:17 +0000148 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))))
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000151
Christian Heimes3feef612008-02-11 06:19:17 +0000152 self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000153 F, 12, 0)
Georg Brandl86b2fb92008-07-16 03:43:04 +0000154 self.assertRaises(TypeError, F, 1.5 + 3j)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000155
Georg Brandl86b2fb92008-07-16 03:43:04 +0000156 self.assertRaises(TypeError, F, "3/2", 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000157 self.assertRaises(TypeError, F, 3, 0j)
158 self.assertRaises(TypeError, F, 3, 1j)
Mark Dickinson7caf9082016-08-23 16:16:52 +0100159 self.assertRaises(TypeError, F, 1, 2, 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000160
Mark Dickinson98127c32010-04-03 11:18:52 +0000161 @requires_IEEE_754
162 def testInitFromFloat(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000163 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)))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000167 # 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'))
Mark Dickinson98127c32010-04-03 11:18:52 +0000171
172 def testInitFromDecimal(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000173 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'))))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000179 # 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'))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000184
185 def testFromString(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000186 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")))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000200
201 self.assertRaisesMessage(
Christian Heimes3feef612008-02-11 06:19:17 +0000202 ZeroDivisionError, "Fraction(3, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000203 F, "3/0")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000204 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000205 ValueError, "Invalid literal for Fraction: '3/'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000206 F, "3/")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000207 self.assertRaisesMessage(
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +0000208 ValueError, "Invalid literal for Fraction: '/2'",
209 F, "/2")
210 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000211 ValueError, "Invalid literal for Fraction: '3 /2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000212 F, "3 /2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000213 self.assertRaisesMessage(
214 # Denominators don't need a sign.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000215 ValueError, "Invalid literal for Fraction: '3/+2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000216 F, "3/+2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000217 self.assertRaisesMessage(
218 # Imitate float's parsing.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000219 ValueError, "Invalid literal for Fraction: '+ 3/2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000220 F, "+ 3/2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000221 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000222 # Avoid treating '.' as a regex special character.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000223 ValueError, "Invalid literal for Fraction: '3a2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000224 F, "3a2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000225 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000226 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000227 ValueError, "Invalid literal for Fraction: '3/7.2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000228 F, "3/7.2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000229 self.assertRaisesMessage(
230 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000231 ValueError, "Invalid literal for Fraction: '3.2/7'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000232 F, "3.2/7")
Christian Heimes292d3512008-02-03 16:51:08 +0000233 self.assertRaisesMessage(
234 # Allow 3. and .3, but not .
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000235 ValueError, "Invalid literal for Fraction: '.'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000236 F, ".")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000237
238 def testImmutable(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000239 r = F(7, 3)
Christian Heimes587c2bf2008-01-19 16:21:02 +0000240 r.__init__(2, 15)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000241 self.assertEqual((7, 3), _components(r))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000242
Christian Heimes400adb02008-02-01 08:12:03 +0000243 self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
244 self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000245 self.assertEqual((7, 3), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000246
247 # But if you _really_ need to:
248 r._numerator = 4
249 r._denominator = 2
Ezio Melottib3aedd42010-11-20 19:04:17 +0000250 self.assertEqual((4, 2), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000251 # Which breaks some important operations:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000252 self.assertNotEqual(F(4, 2), r)
Christian Heimes400adb02008-02-01 08:12:03 +0000253
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000254 def testFromFloat(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000255 self.assertRaises(TypeError, F.from_float, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000256 self.assertEqual((10, 1), _components(F.from_float(10)))
Georg Brandl3a9b0622009-01-03 22:07:57 +0000257 bigint = 1234567890123456789
Ezio Melottib3aedd42010-11-20 19:04:17 +0000258 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000268
269 inf = 1e1000
270 nan = inf - inf
Mark Dickinson73726aa2012-11-15 20:58:40 +0000271 # bug 16469: error types should be consistent with float -> int
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000272 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200273 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000274 F.from_float, inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000275 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200276 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000277 F.from_float, -inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000278 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200279 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000280 F.from_float, nan)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000281
Christian Heimes587c2bf2008-01-19 16:21:02 +0000282 def testFromDecimal(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000283 self.assertRaises(TypeError, F.from_decimal, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000284 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)))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000291
Mark Dickinson73726aa2012-11-15 20:58:40 +0000292 # bug 16469: error types should be consistent with decimal -> int
Christian Heimes587c2bf2008-01-19 16:21:02 +0000293 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200294 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000295 F.from_decimal, Decimal("inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000296 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200297 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000298 F.from_decimal, Decimal("-inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000299 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200300 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000301 F.from_decimal, Decimal("nan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000302 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200303 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000304 F.from_decimal, Decimal("snan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000305
Miss Islington (bot)5ba1cb02019-08-11 15:02:23 -0700306 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
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000312 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))
Ezio Melotti682d3742012-02-29 14:05:53 +0200321 for i in (0, -1):
322 self.assertRaisesMessage(
323 ValueError, "max_denominator should be at least 1",
324 F(1).limit_denominator, i)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000325
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000326 def testConversions(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000327 self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200328 self.assertTypedEquals(1, math.trunc(F(11, 10)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000329 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000337
Ezio Melottib3aedd42010-11-20 19:04:17 +0000338 self.assertEqual(False, bool(F(0, 1)))
339 self.assertEqual(True, bool(F(3, 2)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000340 self.assertTypedEquals(0.1, float(F(1, 10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000341
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'))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000345 self.assertAlmostEqual(2.0/3,
346 float(F(int('2'*400+'7'), int('3'*400+'1'))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000347
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000348 self.assertTypedEquals(0.1+0j, complex(F(1,10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000349
Miss Islington (bot)0d03a102020-02-06 07:13:38 -0800350 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000386 def testRound(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000387 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000392
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000393 def testArithmetic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000394 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))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000398 self.assertTypedEquals(2, F(9, 10) // F(2, 5))
399 self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100400 self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000401 self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100402 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)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000404 self.assertEqual(F(8, 27), F(2, 3) ** F(3))
405 self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000406 self.assertTypedEquals(2.0, F(4) ** F(1, 2))
Ezio Melotti682d3742012-02-29 14:05:53 +0200407 self.assertEqual(F(1, 1), +F(1, 1))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000408 z = pow(F(-1), F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000409 self.assertAlmostEqual(z.real, 0)
410 self.assertEqual(z.imag, 1)
Mark Dickinson84479652016-08-22 10:50:53 +0100411 # 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000424
Stefan Behnel3a374e02019-01-02 13:22:06 +0100425 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000459 def testMixedArithmetic(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000460 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000466
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000467 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000473
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000474 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000480
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000481 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000487
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000488 self.assertTypedEquals(0, F(1, 10) // 1)
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700489 self.assertTypedEquals(0.0, F(1, 10) // 1.0)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000490 self.assertTypedEquals(10, 1 // F(1, 10))
491 self.assertTypedEquals(10**23, 10**22 // F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700492 self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000493
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000494 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))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700497 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'))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000502
Stefan Behnel3a374e02019-01-02 13:22:06 +0100503 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')))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000511
512 # ** has more interesting conversion rules.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000513 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))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000519 self.assertAlmostEqual(0, z.real)
520 self.assertEqual(1, z.imag)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000521 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))
Mark Dickinson3c286e22014-04-05 09:29:00 +0100525 self.assertRaises(ZeroDivisionError, operator.pow,
526 F(0, 1), -2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000527
528 def testMixingWithDecimal(self):
Mark Dickinson08ade6f2010-06-11 10:44:52 +0000529 # Decimal refuses mixed arithmetic (but not mixed comparisons)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100530 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000534
535 def testComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000536 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000545
Mark Dickinson85424c92009-07-18 14:41:42 +0000546 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000590 def testMixedLess(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000591 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000595
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000596 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000600
Mark Dickinson85424c92009-07-18 14:41:42 +0000601 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000608 def testMixedLessEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000609 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000617
Mark Dickinson85424c92009-07-18 14:41:42 +0000618 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000625 def testBigFloatComparisons(self):
626 # Because 10**23 can't be represented exactly as a float:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000627 self.assertFalse(F(10**23) == float(10**23))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000628 # The first test demonstrates why these are important.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000629 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000634
635 def testBigComplexComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000636 self.assertFalse(F(10**23) == complex(10**23))
Mark Dickinson327f02c2010-03-27 11:11:13 +0000637 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000652
653 def testMixedEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000654 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)
Mark Dickinson85424c92009-07-18 14:41:42 +0000662 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000666
667 def testStringification(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000668 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000675
676 def testHash(self):
Ezio Melotti682d3742012-02-29 14:05:53 +0200677 hmod = sys.hash_info.modulus
678 hinf = sys.hash_info.inf
Ezio Melottib3aedd42010-11-20 19:04:17 +0000679 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)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200682 self.assertEqual(hinf, hash(F(1, hmod)))
Mark Dickinsonfec66202010-11-13 10:27:38 +0000683 # Check that __hash__ produces the same value as hash(), for
684 # consistency with int and Decimal. (See issue #10356.)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000685 self.assertEqual(hash(F(-1)), F(-1).__hash__())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000686
687 def testApproximatePi(self):
688 # Algorithm borrowed from
689 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000690 three = F(3)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000691 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000692 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000693 lasts = s
694 n, na = n+na, na+8
695 d, da = d+da, da+32
696 t = (t * n) / d
697 s += t
Ezio Melottib3aedd42010-11-20 19:04:17 +0000698 self.assertAlmostEqual(math.pi, s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000699
700 def testApproximateCos1(self):
701 # Algorithm borrowed from
702 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000703 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):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000706 lasts = s
707 i += 2
708 fact *= i * (i-1)
709 num *= x * x
710 sign *= -1
711 s += num / fact * sign
Ezio Melottib3aedd42010-11-20 19:04:17 +0000712 self.assertAlmostEqual(math.cos(1), s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000713
Christian Heimes969fe572008-01-25 11:23:10 +0000714 def test_copy_deepcopy_pickle(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000715 r = F(13, 7)
Ezio Melotti682d3742012-02-29 14:05:53 +0200716 dr = DummyFraction(13, 7)
Christian Heimes969fe572008-01-25 11:23:10 +0000717 self.assertEqual(r, loads(dumps(r)))
718 self.assertEqual(id(r), id(copy(r)))
719 self.assertEqual(id(r), id(deepcopy(r)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200720 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))
Christian Heimes969fe572008-01-25 11:23:10 +0000724
Mark Dickinsonc28ad272009-02-12 17:58:36 +0000725 def test_slots(self):
726 # Issue 4998
727 r = F(13, 7)
728 self.assertRaises(AttributeError, setattr, r, 'a', 10)
729
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000730if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500731 unittest.main()