test_fractions.py 17.1 KB
Newer Older
Christian Heimes's avatar
Christian Heimes committed
1
"""Tests for Lib/fractions.py."""
2 3

from decimal import Decimal
4
from test.support import run_unittest
5 6
import math
import operator
Christian Heimes's avatar
Christian Heimes committed
7
import fractions
8
import unittest
9
from copy import copy, deepcopy
Neal Norwitz's avatar
Neal Norwitz committed
10
from pickle import dumps, loads
Christian Heimes's avatar
Christian Heimes committed
11
F = fractions.Fraction
Christian Heimes's avatar
Christian Heimes committed
12
gcd = fractions.gcd
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28


class GcdTest(unittest.TestCase):

    def testMisc(self):
        self.assertEquals(0, gcd(0, 0))
        self.assertEquals(1, gcd(1, 0))
        self.assertEquals(-1, gcd(-1, 0))
        self.assertEquals(1, gcd(0, 1))
        self.assertEquals(-1, gcd(0, -1))
        self.assertEquals(1, gcd(7, 1))
        self.assertEquals(-1, gcd(7, -1))
        self.assertEquals(1, gcd(-23, 15))
        self.assertEquals(12, gcd(120, 84))
        self.assertEquals(-12, gcd(84, -120))

29 30 31 32

def _components(r):
    return (r.numerator, r.denominator)

33

Christian Heimes's avatar
Christian Heimes committed
34
class FractionTest(unittest.TestCase):
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

    def assertTypedEquals(self, expected, actual):
        """Asserts that both the types and values are the same."""
        self.assertEquals(type(expected), type(actual))
        self.assertEquals(expected, actual)

    def assertRaisesMessage(self, exc_type, message,
                            callable, *args, **kwargs):
        """Asserts that callable(*args, **kwargs) raises exc_type(message)."""
        try:
            callable(*args, **kwargs)
        except exc_type as e:
            self.assertEquals(message, str(e))
        else:
            self.fail("%s not raised" % exc_type.__name__)

    def testInit(self):
Christian Heimes's avatar
Christian Heimes committed
52 53 54
        self.assertEquals((0, 1), _components(F()))
        self.assertEquals((7, 1), _components(F(7)))
        self.assertEquals((7, 3), _components(F(F(7, 3))))
55

Christian Heimes's avatar
Christian Heimes committed
56 57 58 59 60 61
        self.assertEquals((-1, 1), _components(F(-1, 1)))
        self.assertEquals((-1, 1), _components(F(1, -1)))
        self.assertEquals((1, 1), _components(F(-2, -2)))
        self.assertEquals((1, 2), _components(F(5, 10)))
        self.assertEquals((7, 15), _components(F(7, 15)))
        self.assertEquals((10**23, 1), _components(F(10**23)))
62

63 64 65 66
        self.assertEquals((3, 77), _components(F(F(3, 7), 11)))
        self.assertEquals((-9, 5), _components(F(2, F(-10, 9))))
        self.assertEquals((2486, 2485), _components(F(F(22, 7), F(355, 113))))

Christian Heimes's avatar
Christian Heimes committed
67
        self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
Christian Heimes's avatar
Christian Heimes committed
68
                                 F, 12, 0)
Georg Brandl's avatar
Georg Brandl committed
69 70
        self.assertRaises(TypeError, F, 1.5)
        self.assertRaises(TypeError, F, 1.5 + 3j)
71

Georg Brandl's avatar
Georg Brandl committed
72
        self.assertRaises(TypeError, F, "3/2", 3)
73 74 75
        self.assertRaises(TypeError, F, 3, 0j)
        self.assertRaises(TypeError, F, 3, 1j)

76 77

    def testFromString(self):
Christian Heimes's avatar
Christian Heimes committed
78 79 80 81 82 83 84 85 86
        self.assertEquals((5, 1), _components(F("5")))
        self.assertEquals((3, 2), _components(F("3/2")))
        self.assertEquals((3, 2), _components(F(" \n  +3/2")))
        self.assertEquals((-3, 2), _components(F("-3/2  ")))
        self.assertEquals((13, 2), _components(F("    013/02 \n  ")))
        self.assertEquals((16, 5), _components(F(" 3.2 ")))
        self.assertEquals((-16, 5), _components(F(" -3.2 ")))
        self.assertEquals((-3, 1), _components(F(" -3. ")))
        self.assertEquals((3, 5), _components(F(" .6 ")))
87 88 89 90 91
        self.assertEquals((1, 3125), _components(F("32.e-5")))
        self.assertEquals((1000000, 1), _components(F("1E+06")))
        self.assertEquals((-12300, 1), _components(F("-1.23e4")))
        self.assertEquals((0, 1), _components(F(" .0e+0\t")))
        self.assertEquals((0, 1), _components(F("-0.000e0")))
92 93

        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
94
            ZeroDivisionError, "Fraction(3, 0)",
Christian Heimes's avatar
Christian Heimes committed
95
            F, "3/0")
96
        self.assertRaisesMessage(
Benjamin Peterson's avatar
Benjamin Peterson committed
97
            ValueError, "Invalid literal for Fraction: '3/'",
Christian Heimes's avatar
Christian Heimes committed
98
            F, "3/")
99 100 101
        self.assertRaisesMessage(
            ValueError, "Invalid literal for Fraction: '/2'",
            F, "/2")
102
        self.assertRaisesMessage(
Benjamin Peterson's avatar
Benjamin Peterson committed
103
            ValueError, "Invalid literal for Fraction: '3 /2'",
Christian Heimes's avatar
Christian Heimes committed
104
            F, "3 /2")
105 106
        self.assertRaisesMessage(
            # Denominators don't need a sign.
Benjamin Peterson's avatar
Benjamin Peterson committed
107
            ValueError, "Invalid literal for Fraction: '3/+2'",
Christian Heimes's avatar
Christian Heimes committed
108
            F, "3/+2")
109 110
        self.assertRaisesMessage(
            # Imitate float's parsing.
Benjamin Peterson's avatar
Benjamin Peterson committed
111
            ValueError, "Invalid literal for Fraction: '+ 3/2'",
Christian Heimes's avatar
Christian Heimes committed
112
            F, "+ 3/2")
113
        self.assertRaisesMessage(
114
            # Avoid treating '.' as a regex special character.
Benjamin Peterson's avatar
Benjamin Peterson committed
115
            ValueError, "Invalid literal for Fraction: '3a2'",
Christian Heimes's avatar
Christian Heimes committed
116
            F, "3a2")
117 118
        self.assertRaisesMessage(
            # Don't accept combinations of decimals and rationals.
Benjamin Peterson's avatar
Benjamin Peterson committed
119
            ValueError, "Invalid literal for Fraction: '3/7.2'",
Christian Heimes's avatar
Christian Heimes committed
120
            F, "3/7.2")
121 122
        self.assertRaisesMessage(
            # Don't accept combinations of decimals and rationals.
Benjamin Peterson's avatar
Benjamin Peterson committed
123
            ValueError, "Invalid literal for Fraction: '3.2/7'",
Christian Heimes's avatar
Christian Heimes committed
124
            F, "3.2/7")
Christian Heimes's avatar
Christian Heimes committed
125 126
        self.assertRaisesMessage(
            # Allow 3. and .3, but not .
Benjamin Peterson's avatar
Benjamin Peterson committed
127
            ValueError, "Invalid literal for Fraction: '.'",
Christian Heimes's avatar
Christian Heimes committed
128
            F, ".")
129 130

    def testImmutable(self):
Christian Heimes's avatar
Christian Heimes committed
131
        r = F(7, 3)
132 133 134
        r.__init__(2, 15)
        self.assertEquals((7, 3), _components(r))

135 136 137 138 139 140 141 142 143
        self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
        self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
        self.assertEquals((7, 3), _components(r))

        # But if you _really_ need to:
        r._numerator = 4
        r._denominator = 2
        self.assertEquals((4, 2), _components(r))
        # Which breaks some important operations:
Christian Heimes's avatar
Christian Heimes committed
144
        self.assertNotEquals(F(4, 2), r)
145

146
    def testFromFloat(self):
Georg Brandl's avatar
Georg Brandl committed
147 148
        self.assertRaises(TypeError, F.from_float, 3+4j)
        self.assertEquals((10, 1), _components(F.from_float(10)))
149 150
        bigint = 1234567890123456789
        self.assertEquals((bigint, 1), _components(F.from_float(bigint)))
Christian Heimes's avatar
Christian Heimes committed
151 152 153
        self.assertEquals((0, 1), _components(F.from_float(-0.0)))
        self.assertEquals((10, 1), _components(F.from_float(10.0)))
        self.assertEquals((-5, 2), _components(F.from_float(-2.5)))
154
        self.assertEquals((99999999999999991611392, 1),
Christian Heimes's avatar
Christian Heimes committed
155 156
                          _components(F.from_float(1e23)))
        self.assertEquals(float(10**23), float(F.from_float(1e23)))
157
        self.assertEquals((3602879701896397, 1125899906842624),
Christian Heimes's avatar
Christian Heimes committed
158 159
                          _components(F.from_float(3.2)))
        self.assertEquals(3.2, float(F.from_float(3.2)))
160 161 162 163

        inf = 1e1000
        nan = inf - inf
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
164
            TypeError, "Cannot convert inf to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
165
            F.from_float, inf)
166
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
167
            TypeError, "Cannot convert -inf to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
168
            F.from_float, -inf)
169
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
170
            TypeError, "Cannot convert nan to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
171
            F.from_float, nan)
172

173
    def testFromDecimal(self):
Georg Brandl's avatar
Georg Brandl committed
174 175
        self.assertRaises(TypeError, F.from_decimal, 3+4j)
        self.assertEquals(F(10, 1), F.from_decimal(10))
Christian Heimes's avatar
Christian Heimes committed
176 177 178 179 180 181
        self.assertEquals(F(0), F.from_decimal(Decimal("-0")))
        self.assertEquals(F(5, 10), F.from_decimal(Decimal("0.5")))
        self.assertEquals(F(5, 1000), F.from_decimal(Decimal("5e-3")))
        self.assertEquals(F(5000), F.from_decimal(Decimal("5e3")))
        self.assertEquals(1 - F(1, 10**30),
                          F.from_decimal(Decimal("0." + "9" * 30)))
182 183

        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
184
            TypeError, "Cannot convert Infinity to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
185
            F.from_decimal, Decimal("inf"))
186
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
187
            TypeError, "Cannot convert -Infinity to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
188
            F.from_decimal, Decimal("-inf"))
189
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
190
            TypeError, "Cannot convert NaN to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
191
            F.from_decimal, Decimal("nan"))
192
        self.assertRaisesMessage(
Christian Heimes's avatar
Christian Heimes committed
193
            TypeError, "Cannot convert sNaN to Fraction.",
Christian Heimes's avatar
Christian Heimes committed
194 195 196 197 198 199 200 201 202 203 204
            F.from_decimal, Decimal("snan"))

    def testLimitDenominator(self):
        rpi = F('3.1415926535897932')
        self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
        self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
        self.assertEqual(rpi.limit_denominator(113), F(355, 113))
        self.assertEqual(rpi.limit_denominator(112), F(333, 106))
        self.assertEqual(F(201, 200).limit_denominator(100), F(1))
        self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
        self.assertEqual(F(0).limit_denominator(10000), F(0))
205

206
    def testConversions(self):
Christian Heimes's avatar
Christian Heimes committed
207 208 209 210 211 212 213 214 215 216 217 218 219
        self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
        self.assertTypedEquals(-2, math.floor(F(-11, 10)))
        self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
        self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
        self.assertTypedEquals(-1, int(F(-11, 10)))
        self.assertTypedEquals(0, round(F(-1, 10)))
        self.assertTypedEquals(0, round(F(-5, 10)))
        self.assertTypedEquals(-2, round(F(-15, 10)))
        self.assertTypedEquals(-1, round(F(-7, 10)))

        self.assertEquals(False, bool(F(0, 1)))
        self.assertEquals(True, bool(F(3, 2)))
        self.assertTypedEquals(0.1, float(F(1, 10)))
220 221 222 223 224

        # Check that __float__ isn't implemented by converting the
        # numerator and denominator to float before dividing.
        self.assertRaises(OverflowError, float, int('2'*400+'7'))
        self.assertAlmostEquals(2.0/3,
Christian Heimes's avatar
Christian Heimes committed
225
                                float(F(int('2'*400+'7'), int('3'*400+'1'))))
226

Christian Heimes's avatar
Christian Heimes committed
227
        self.assertTypedEquals(0.1+0j, complex(F(1,10)))
228 229

    def testRound(self):
Christian Heimes's avatar
Christian Heimes committed
230 231 232 233 234
        self.assertTypedEquals(F(-200), round(F(-150), -2))
        self.assertTypedEquals(F(-200), round(F(-250), -2))
        self.assertTypedEquals(F(30), round(F(26), -1))
        self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
        self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
235 236 237


    def testArithmetic(self):
Christian Heimes's avatar
Christian Heimes committed
238 239 240 241 242 243 244 245 246 247 248
        self.assertEquals(F(1, 2), F(1, 10) + F(2, 5))
        self.assertEquals(F(-3, 10), F(1, 10) - F(2, 5))
        self.assertEquals(F(1, 25), F(1, 10) * F(2, 5))
        self.assertEquals(F(1, 4), F(1, 10) / F(2, 5))
        self.assertTypedEquals(2, F(9, 10) // F(2, 5))
        self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
        self.assertEquals(F(2, 3), F(-7, 3) % F(3, 2))
        self.assertEquals(F(8, 27), F(2, 3) ** F(3))
        self.assertEquals(F(27, 8), F(2, 3) ** F(-3))
        self.assertTypedEquals(2.0, F(4) ** F(1, 2))
        z = pow(F(-1), F(1, 2))
249 250 251 252
        self.assertAlmostEquals(z.real, 0)
        self.assertEquals(z.imag, 1)

    def testMixedArithmetic(self):
Christian Heimes's avatar
Christian Heimes committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
        self.assertTypedEquals(1.1, F(1, 10) + 1.0)
        self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
        self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
        self.assertTypedEquals(1.1, 1.0 + F(1, 10))
        self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))

        self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
        self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
        self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
        self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
        self.assertTypedEquals(0.9, 1.0 - F(1, 10))
        self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))

        self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
        self.assertTypedEquals(0.1, F(1, 10) * 1.0)
        self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
        self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
        self.assertTypedEquals(0.1, 1.0 * F(1, 10))
        self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))

        self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
        self.assertTypedEquals(0.1, F(1, 10) / 1.0)
        self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
        self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
        self.assertTypedEquals(10.0, 1.0 / F(1, 10))
        self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))

        self.assertTypedEquals(0, F(1, 10) // 1)
        self.assertTypedEquals(0, F(1, 10) // 1.0)
        self.assertTypedEquals(10, 1 // F(1, 10))
        self.assertTypedEquals(10**23, 10**22 // F(1, 10))
        self.assertTypedEquals(10, 1.0 // F(1, 10))

        self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
        self.assertTypedEquals(0.1, F(1, 10) % 1.0)
        self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
        self.assertTypedEquals(0.0, 1.0 % F(1, 10))
291 292 293 294

        # No need for divmod since we don't override it.

        # ** has more interesting conversion rules.
Christian Heimes's avatar
Christian Heimes committed
295 296 297 298 299 300
        self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
        self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
        self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
        self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
        self.assertTypedEquals(4 , 2 ** F(2, 1))
        z = pow(-1, F(1, 2))
301 302
        self.assertAlmostEquals(0, z.real)
        self.assertEquals(1, z.imag)
Christian Heimes's avatar
Christian Heimes committed
303 304 305 306
        self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
        self.assertTypedEquals(2.0 , 4 ** F(1, 2))
        self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
        self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
307 308

    def testMixingWithDecimal(self):
309
        # Decimal refuses mixed comparisons.
310 311
        self.assertRaisesMessage(
            TypeError,
Christian Heimes's avatar
Christian Heimes committed
312
            "unsupported operand type(s) for +: 'Fraction' and 'Decimal'",
Christian Heimes's avatar
Christian Heimes committed
313 314
            operator.add, F(3,11), Decimal('3.1415926'))
        self.assertNotEquals(F(5, 2), Decimal('2.5'))
315 316

    def testComparisons(self):
Christian Heimes's avatar
Christian Heimes committed
317 318 319 320 321 322 323 324 325
        self.assertTrue(F(1, 2) < F(2, 3))
        self.assertFalse(F(1, 2) < F(1, 2))
        self.assertTrue(F(1, 2) <= F(2, 3))
        self.assertTrue(F(1, 2) <= F(1, 2))
        self.assertFalse(F(2, 3) <= F(1, 2))
        self.assertTrue(F(1, 2) == F(1, 2))
        self.assertFalse(F(1, 2) == F(1, 3))
        self.assertFalse(F(1, 2) != F(1, 2))
        self.assertTrue(F(1, 2) != F(1, 3))
326 327

    def testMixedLess(self):
Christian Heimes's avatar
Christian Heimes committed
328 329 330 331
        self.assertTrue(2 < F(5, 2))
        self.assertFalse(2 < F(4, 2))
        self.assertTrue(F(5, 2) < 3)
        self.assertFalse(F(4, 2) < 2)
332

Christian Heimes's avatar
Christian Heimes committed
333 334 335 336
        self.assertTrue(F(1, 2) < 0.6)
        self.assertFalse(F(1, 2) < 0.4)
        self.assertTrue(0.4 < F(1, 2))
        self.assertFalse(0.5 < F(1, 2))
337 338

    def testMixedLessEqual(self):
Christian Heimes's avatar
Christian Heimes committed
339 340 341 342 343 344 345 346
        self.assertTrue(0.5 <= F(1, 2))
        self.assertFalse(0.6 <= F(1, 2))
        self.assertTrue(F(1, 2) <= 0.5)
        self.assertFalse(F(1, 2) <= 0.4)
        self.assertTrue(2 <= F(4, 2))
        self.assertFalse(2 <= F(3, 2))
        self.assertTrue(F(4, 2) <= 2)
        self.assertFalse(F(5, 2) <= 2)
347 348 349

    def testBigFloatComparisons(self):
        # Because 10**23 can't be represented exactly as a float:
Christian Heimes's avatar
Christian Heimes committed
350
        self.assertFalse(F(10**23) == float(10**23))
351
        # The first test demonstrates why these are important.
Christian Heimes's avatar
Christian Heimes committed
352 353 354 355 356
        self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
        self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
        self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
        self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
        self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
357 358

    def testBigComplexComparisons(self):
Christian Heimes's avatar
Christian Heimes committed
359 360 361
        self.assertFalse(F(10**23) == complex(10**23))
        self.assertTrue(F(10**23) > complex(10**23))
        self.assertFalse(F(10**23) <= complex(10**23))
362 363

    def testMixedEqual(self):
Christian Heimes's avatar
Christian Heimes committed
364 365 366 367 368 369 370 371
        self.assertTrue(0.5 == F(1, 2))
        self.assertFalse(0.6 == F(1, 2))
        self.assertTrue(F(1, 2) == 0.5)
        self.assertFalse(F(1, 2) == 0.4)
        self.assertTrue(2 == F(4, 2))
        self.assertFalse(2 == F(3, 2))
        self.assertTrue(F(4, 2) == 2)
        self.assertFalse(F(5, 2) == 2)
372 373

    def testStringification(self):
Christian Heimes's avatar
Christian Heimes committed
374
        self.assertEquals("Fraction(7, 3)", repr(F(7, 3)))
Benjamin Peterson's avatar
Benjamin Peterson committed
375 376 377 378
        self.assertEquals("Fraction(6283185307, 2000000000)",
                          repr(F('3.1415926535')))
        self.assertEquals("Fraction(-1, 100000000000000000000)",
                          repr(F(1, -10**20)))
Christian Heimes's avatar
Christian Heimes committed
379 380
        self.assertEquals("7/3", str(F(7, 3)))
        self.assertEquals("7", str(F(7, 1)))
381 382

    def testHash(self):
Christian Heimes's avatar
Christian Heimes committed
383 384 385
        self.assertEquals(hash(2.5), hash(F(5, 2)))
        self.assertEquals(hash(10**50), hash(F(10**50)))
        self.assertNotEquals(hash(float(10**23)), hash(F(10**23)))
386 387 388 389

    def testApproximatePi(self):
        # Algorithm borrowed from
        # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes's avatar
Christian Heimes committed
390
        three = F(3)
391
        lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
Christian Heimes's avatar
Christian Heimes committed
392
        while abs(s - lasts) > F(1, 10**9):
393 394 395 396 397 398 399 400 401 402
            lasts = s
            n, na = n+na, na+8
            d, da = d+da, da+32
            t = (t * n) / d
            s += t
        self.assertAlmostEquals(math.pi, s)

    def testApproximateCos1(self):
        # Algorithm borrowed from
        # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes's avatar
Christian Heimes committed
403 404 405
        x = F(1)
        i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
        while abs(s - lasts) > F(1, 10**9):
406 407 408 409 410 411 412 413
            lasts = s
            i += 2
            fact *= i * (i-1)
            num *= x * x
            sign *= -1
            s += num / fact * sign
        self.assertAlmostEquals(math.cos(1), s)

414
    def test_copy_deepcopy_pickle(self):
Christian Heimes's avatar
Christian Heimes committed
415
        r = F(13, 7)
416 417 418 419
        self.assertEqual(r, loads(dumps(r)))
        self.assertEqual(id(r), id(copy(r)))
        self.assertEqual(id(r), id(deepcopy(r)))

420 421 422 423 424
    def test_slots(self):
        # Issue 4998
        r = F(13, 7)
        self.assertRaises(AttributeError, setattr, r, 'a', 10)

425
def test_main():
Christian Heimes's avatar
Christian Heimes committed
426
    run_unittest(FractionTest, GcdTest)
427 428 429

if __name__ == '__main__':
    test_main()