1 """Tests for Lib/fractions.py.""" 2 3 from decimal import Decimal 4 from test.test_support import run_unittest 5 import math 6 import numbers 7 import operator 8 import fractions 9 import unittest 10 from copy import copy, deepcopy 11 from cPickle import dumps, loads 12 F = fractions.Fraction 13 gcd = fractions.gcd 14 15 # decorator for skipping tests on non-IEEE 754 platforms 16 requires_IEEE_754 = unittest.skipUnless( 17 float.__getformat__("double").startswith("IEEE"), 18 "test requires IEEE 754 doubles") 19 20 class DummyFloat(object): 21 """Dummy float class for testing comparisons with Fractions""" 22 23 def __init__(self, value): 24 if not isinstance(value, float): 25 raise TypeError("DummyFloat can only be initialized from float") 26 self.value = value 27 28 def _richcmp(self, other, op): 29 if isinstance(other, numbers.Rational): 30 return op(F.from_float(self.value), other) 31 elif isinstance(other, DummyFloat): 32 return op(self.value, other.value) 33 else: 34 return NotImplemented 35 36 def __eq__(self, other): return self._richcmp(other, operator.eq) 37 def __le__(self, other): return self._richcmp(other, operator.le) 38 def __lt__(self, other): return self._richcmp(other, operator.lt) 39 def __ge__(self, other): return self._richcmp(other, operator.ge) 40 def __gt__(self, other): return self._richcmp(other, operator.gt) 41 42 # shouldn't be calling __float__ at all when doing comparisons 43 def __float__(self): 44 assert False, "__float__ should not be invoked for comparisons" 45 46 # same goes for subtraction 47 def __sub__(self, other): 48 assert False, "__sub__ should not be invoked for comparisons" 49 __rsub__ = __sub__ 50 51 # Silence Py3k warning 52 __hash__ = None 53 54 55 class DummyRational(object): 56 """Test comparison of Fraction with a naive rational implementation.""" 57 58 def __init__(self, num, den): 59 g = gcd(num, den) 60 self.num = num // g 61 self.den = den // g 62 63 def __eq__(self, other): 64 if isinstance(other, fractions.Fraction): 65 return (self.num == other._numerator and 66 self.den == other._denominator) 67 else: 68 return NotImplemented 69 70 def __lt__(self, other): 71 return(self.num * other._denominator < self.den * other._numerator) 72 73 def __gt__(self, other): 74 return(self.num * other._denominator > self.den * other._numerator) 75 76 def __le__(self, other): 77 return(self.num * other._denominator <= self.den * other._numerator) 78 79 def __ge__(self, other): 80 return(self.num * other._denominator >= self.den * other._numerator) 81 82 # this class is for testing comparisons; conversion to float 83 # should never be used for a comparison, since it loses accuracy 84 def __float__(self): 85 assert False, "__float__ should not be invoked" 86 87 # Silence Py3k warning 88 __hash__ = None 89 90 91 class GcdTest(unittest.TestCase): 92 93 def testMisc(self): 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 105 106 def _components(r): 107 return (r.numerator, r.denominator) 108 109 110 class FractionTest(unittest.TestCase): 111 112 def assertTypedEquals(self, expected, actual): 113 """Asserts that both the types and values are the same.""" 114 self.assertEqual(type(expected), type(actual)) 115 self.assertEqual(expected, actual) 116 117 def assertRaisesMessage(self, exc_type, message, 118 callable, *args, **kwargs): 119 """Asserts that callable(*args, **kwargs) raises exc_type(message).""" 120 try: 121 callable(*args, **kwargs) 122 except exc_type, e: 123 self.assertEqual(message, str(e)) 124 else: 125 self.fail("%s not raised" % exc_type.__name__) 126 127 def testInit(self): 128 self.assertEqual((0, 1), _components(F())) 129 self.assertEqual((7, 1), _components(F(7))) 130 self.assertEqual((7, 3), _components(F(F(7, 3)))) 131 132 self.assertEqual((-1, 1), _components(F(-1, 1))) 133 self.assertEqual((-1, 1), _components(F(1, -1))) 134 self.assertEqual((1, 1), _components(F(-2, -2))) 135 self.assertEqual((1, 2), _components(F(5, 10))) 136 self.assertEqual((7, 15), _components(F(7, 15))) 137 self.assertEqual((10**23, 1), _components(F(10**23))) 138 139 self.assertEqual((3, 77), _components(F(F(3, 7), 11))) 140 self.assertEqual((-9, 5), _components(F(2, F(-10, 9)))) 141 self.assertEqual((2486, 2485), _components(F(F(22, 7), F(355, 113)))) 142 143 self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)", 144 F, 12, 0) 145 self.assertRaises(TypeError, F, 1.5 + 3j) 146 147 self.assertRaises(TypeError, F, "3/2", 3) 148 self.assertRaises(TypeError, F, 3, 0j) 149 self.assertRaises(TypeError, F, 3, 1j) 150 151 @requires_IEEE_754 152 def testInitFromFloat(self): 153 self.assertEqual((5, 2), _components(F(2.5))) 154 self.assertEqual((0, 1), _components(F(-0.0))) 155 self.assertEqual((3602879701896397, 36028797018963968), 156 _components(F(0.1))) 157 self.assertRaises(TypeError, F, float('nan')) 158 self.assertRaises(TypeError, F, float('inf')) 159 self.assertRaises(TypeError, F, float('-inf')) 160 161 def testInitFromDecimal(self): 162 self.assertEqual((11, 10), 163 _components(F(Decimal('1.1')))) 164 self.assertEqual((7, 200), 165 _components(F(Decimal('3.5e-2')))) 166 self.assertEqual((0, 1), 167 _components(F(Decimal('.000e20')))) 168 self.assertRaises(TypeError, F, Decimal('nan')) 169 self.assertRaises(TypeError, F, Decimal('snan')) 170 self.assertRaises(TypeError, F, Decimal('inf')) 171 self.assertRaises(TypeError, F, Decimal('-inf')) 172 173 def testFromString(self): 174 self.assertEqual((5, 1), _components(F("5"))) 175 self.assertEqual((3, 2), _components(F("3/2"))) 176 self.assertEqual((3, 2), _components(F(" \n +3/2"))) 177 self.assertEqual((-3, 2), _components(F("-3/2 "))) 178 self.assertEqual((13, 2), _components(F(" 013/02 \n "))) 179 self.assertEqual((13, 2), _components(F(u" 013/02 \n "))) 180 181 self.assertEqual((16, 5), _components(F(" 3.2 "))) 182 self.assertEqual((-16, 5), _components(F(u" -3.2 "))) 183 self.assertEqual((-3, 1), _components(F(u" -3. "))) 184 self.assertEqual((3, 5), _components(F(u" .6 "))) 185 self.assertEqual((1, 3125), _components(F("32.e-5"))) 186 self.assertEqual((1000000, 1), _components(F("1E+06"))) 187 self.assertEqual((-12300, 1), _components(F("-1.23e4"))) 188 self.assertEqual((0, 1), _components(F(" .0e+0\t"))) 189 self.assertEqual((0, 1), _components(F("-0.000e0"))) 190 191 192 self.assertRaisesMessage( 193 ZeroDivisionError, "Fraction(3, 0)", 194 F, "3/0") 195 self.assertRaisesMessage( 196 ValueError, "Invalid literal for Fraction: '3/'", 197 F, "3/") 198 self.assertRaisesMessage( 199 ValueError, "Invalid literal for Fraction: '/2'", 200 F, "/2") 201 self.assertRaisesMessage( 202 ValueError, "Invalid literal for Fraction: '3 /2'", 203 F, "3 /2") 204 self.assertRaisesMessage( 205 # Denominators don't need a sign. 206 ValueError, "Invalid literal for Fraction: '3/+2'", 207 F, "3/+2") 208 self.assertRaisesMessage( 209 # Imitate float's parsing. 210 ValueError, "Invalid literal for Fraction: '+ 3/2'", 211 F, "+ 3/2") 212 self.assertRaisesMessage( 213 # Avoid treating '.' as a regex special character. 214 ValueError, "Invalid literal for Fraction: '3a2'", 215 F, "3a2") 216 self.assertRaisesMessage( 217 # Don't accept combinations of decimals and fractions. 218 ValueError, "Invalid literal for Fraction: '3/7.2'", 219 F, "3/7.2") 220 self.assertRaisesMessage( 221 # Don't accept combinations of decimals and fractions. 222 ValueError, "Invalid literal for Fraction: '3.2/7'", 223 F, "3.2/7") 224 self.assertRaisesMessage( 225 # Allow 3. and .3, but not . 226 ValueError, "Invalid literal for Fraction: '.'", 227 F, ".") 228 229 def testImmutable(self): 230 r = F(7, 3) 231 r.__init__(2, 15) 232 self.assertEqual((7, 3), _components(r)) 233 234 self.assertRaises(AttributeError, setattr, r, 'numerator', 12) 235 self.assertRaises(AttributeError, setattr, r, 'denominator', 6) 236 self.assertEqual((7, 3), _components(r)) 237 238 # But if you _really_ need to: 239 r._numerator = 4 240 r._denominator = 2 241 self.assertEqual((4, 2), _components(r)) 242 # Which breaks some important operations: 243 self.assertNotEqual(F(4, 2), r) 244 245 def testFromFloat(self): 246 self.assertRaises(TypeError, F.from_float, 3+4j) 247 self.assertEqual((10, 1), _components(F.from_float(10))) 248 bigint = 1234567890123456789 249 self.assertEqual((bigint, 1), _components(F.from_float(bigint))) 250 self.assertEqual((0, 1), _components(F.from_float(-0.0))) 251 self.assertEqual((10, 1), _components(F.from_float(10.0))) 252 self.assertEqual((-5, 2), _components(F.from_float(-2.5))) 253 self.assertEqual((99999999999999991611392, 1), 254 _components(F.from_float(1e23))) 255 self.assertEqual(float(10**23), float(F.from_float(1e23))) 256 self.assertEqual((3602879701896397, 1125899906842624), 257 _components(F.from_float(3.2))) 258 self.assertEqual(3.2, float(F.from_float(3.2))) 259 260 inf = 1e1000 261 nan = inf - inf 262 self.assertRaisesMessage( 263 TypeError, "Cannot convert inf to Fraction.", 264 F.from_float, inf) 265 self.assertRaisesMessage( 266 TypeError, "Cannot convert -inf to Fraction.", 267 F.from_float, -inf) 268 self.assertRaisesMessage( 269 TypeError, "Cannot convert nan to Fraction.", 270 F.from_float, nan) 271 272 def testFromDecimal(self): 273 self.assertRaises(TypeError, F.from_decimal, 3+4j) 274 self.assertEqual(F(10, 1), F.from_decimal(10)) 275 self.assertEqual(F(0), F.from_decimal(Decimal("-0"))) 276 self.assertEqual(F(5, 10), F.from_decimal(Decimal("0.5"))) 277 self.assertEqual(F(5, 1000), F.from_decimal(Decimal("5e-3"))) 278 self.assertEqual(F(5000), F.from_decimal(Decimal("5e3"))) 279 self.assertEqual(1 - F(1, 10**30), 280 F.from_decimal(Decimal("0." + "9" * 30))) 281 282 self.assertRaisesMessage( 283 TypeError, "Cannot convert Infinity to Fraction.", 284 F.from_decimal, Decimal("inf")) 285 self.assertRaisesMessage( 286 TypeError, "Cannot convert -Infinity to Fraction.", 287 F.from_decimal, Decimal("-inf")) 288 self.assertRaisesMessage( 289 TypeError, "Cannot convert NaN to Fraction.", 290 F.from_decimal, Decimal("nan")) 291 self.assertRaisesMessage( 292 TypeError, "Cannot convert sNaN to Fraction.", 293 F.from_decimal, Decimal("snan")) 294 295 def testLimitDenominator(self): 296 rpi = F('3.1415926535897932') 297 self.assertEqual(rpi.limit_denominator(10000), F(355, 113)) 298 self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113)) 299 self.assertEqual(rpi.limit_denominator(113), F(355, 113)) 300 self.assertEqual(rpi.limit_denominator(112), F(333, 106)) 301 self.assertEqual(F(201, 200).limit_denominator(100), F(1)) 302 self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101)) 303 self.assertEqual(F(0).limit_denominator(10000), F(0)) 304 305 def testConversions(self): 306 self.assertTypedEquals(-1, math.trunc(F(-11, 10))) 307 self.assertTypedEquals(-1, int(F(-11, 10))) 308 309 self.assertEqual(False, bool(F(0, 1))) 310 self.assertEqual(True, bool(F(3, 2))) 311 self.assertTypedEquals(0.1, float(F(1, 10))) 312 313 # Check that __float__ isn't implemented by converting the 314 # numerator and denominator to float before dividing. 315 self.assertRaises(OverflowError, float, long('2'*400+'7')) 316 self.assertAlmostEqual(2.0/3, 317 float(F(long('2'*400+'7'), long('3'*400+'1')))) 318 319 self.assertTypedEquals(0.1+0j, complex(F(1,10))) 320 321 322 def testArithmetic(self): 323 self.assertEqual(F(1, 2), F(1, 10) + F(2, 5)) 324 self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5)) 325 self.assertEqual(F(1, 25), F(1, 10) * F(2, 5)) 326 self.assertEqual(F(1, 4), F(1, 10) / F(2, 5)) 327 self.assertTypedEquals(2, F(9, 10) // F(2, 5)) 328 self.assertTypedEquals(10**23, F(10**23, 1) // F(1)) 329 self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2)) 330 self.assertEqual(F(8, 27), F(2, 3) ** F(3)) 331 self.assertEqual(F(27, 8), F(2, 3) ** F(-3)) 332 self.assertTypedEquals(2.0, F(4) ** F(1, 2)) 333 # Will return 1j in 3.0: 334 self.assertRaises(ValueError, pow, F(-1), F(1, 2)) 335 336 def testMixedArithmetic(self): 337 self.assertTypedEquals(F(11, 10), F(1, 10) + 1) 338 self.assertTypedEquals(1.1, F(1, 10) + 1.0) 339 self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j)) 340 self.assertTypedEquals(F(11, 10), 1 + F(1, 10)) 341 self.assertTypedEquals(1.1, 1.0 + F(1, 10)) 342 self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10)) 343 344 self.assertTypedEquals(F(-9, 10), F(1, 10) - 1) 345 self.assertTypedEquals(-0.9, F(1, 10) - 1.0) 346 self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j)) 347 self.assertTypedEquals(F(9, 10), 1 - F(1, 10)) 348 self.assertTypedEquals(0.9, 1.0 - F(1, 10)) 349 self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10)) 350 351 self.assertTypedEquals(F(1, 10), F(1, 10) * 1) 352 self.assertTypedEquals(0.1, F(1, 10) * 1.0) 353 self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j)) 354 self.assertTypedEquals(F(1, 10), 1 * F(1, 10)) 355 self.assertTypedEquals(0.1, 1.0 * F(1, 10)) 356 self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10)) 357 358 self.assertTypedEquals(F(1, 10), F(1, 10) / 1) 359 self.assertTypedEquals(0.1, F(1, 10) / 1.0) 360 self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j)) 361 self.assertTypedEquals(F(10, 1), 1 / F(1, 10)) 362 self.assertTypedEquals(10.0, 1.0 / F(1, 10)) 363 self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10)) 364 365 self.assertTypedEquals(0, F(1, 10) // 1) 366 self.assertTypedEquals(0.0, F(1, 10) // 1.0) 367 self.assertTypedEquals(10, 1 // F(1, 10)) 368 self.assertTypedEquals(10**23, 10**22 // F(1, 10)) 369 self.assertTypedEquals(10.0, 1.0 // F(1, 10)) 370 371 self.assertTypedEquals(F(1, 10), F(1, 10) % 1) 372 self.assertTypedEquals(0.1, F(1, 10) % 1.0) 373 self.assertTypedEquals(F(0, 1), 1 % F(1, 10)) 374 self.assertTypedEquals(0.0, 1.0 % F(1, 10)) 375 376 # No need for divmod since we don't override it. 377 378 # ** has more interesting conversion rules. 379 self.assertTypedEquals(F(100, 1), F(1, 10) ** -2) 380 self.assertTypedEquals(F(100, 1), F(10, 1) ** 2) 381 self.assertTypedEquals(0.1, F(1, 10) ** 1.0) 382 self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j)) 383 self.assertTypedEquals(4 , 2 ** F(2, 1)) 384 # Will return 1j in 3.0: 385 self.assertRaises(ValueError, pow, (-1), F(1, 2)) 386 self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1)) 387 self.assertTypedEquals(2.0 , 4 ** F(1, 2)) 388 self.assertTypedEquals(0.25, 2.0 ** F(-2, 1)) 389 self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10)) 390 391 def testMixingWithDecimal(self): 392 # Decimal refuses mixed comparisons. 393 self.assertRaisesMessage( 394 TypeError, 395 "unsupported operand type(s) for +: 'Fraction' and 'Decimal'", 396 operator.add, F(3,11), Decimal('3.1415926')) 397 self.assertNotEqual(F(5, 2), Decimal('2.5')) 398 399 def testComparisons(self): 400 self.assertTrue(F(1, 2) < F(2, 3)) 401 self.assertFalse(F(1, 2) < F(1, 2)) 402 self.assertTrue(F(1, 2) <= F(2, 3)) 403 self.assertTrue(F(1, 2) <= F(1, 2)) 404 self.assertFalse(F(2, 3) <= F(1, 2)) 405 self.assertTrue(F(1, 2) == F(1, 2)) 406 self.assertFalse(F(1, 2) == F(1, 3)) 407 self.assertFalse(F(1, 2) != F(1, 2)) 408 self.assertTrue(F(1, 2) != F(1, 3)) 409 410 def testComparisonsDummyRational(self): 411 self.assertTrue(F(1, 2) == DummyRational(1, 2)) 412 self.assertTrue(DummyRational(1, 2) == F(1, 2)) 413 self.assertFalse(F(1, 2) == DummyRational(3, 4)) 414 self.assertFalse(DummyRational(3, 4) == F(1, 2)) 415 416 self.assertTrue(F(1, 2) < DummyRational(3, 4)) 417 self.assertFalse(F(1, 2) < DummyRational(1, 2)) 418 self.assertFalse(F(1, 2) < DummyRational(1, 7)) 419 self.assertFalse(F(1, 2) > DummyRational(3, 4)) 420 self.assertFalse(F(1, 2) > DummyRational(1, 2)) 421 self.assertTrue(F(1, 2) > DummyRational(1, 7)) 422 self.assertTrue(F(1, 2) <= DummyRational(3, 4)) 423 self.assertTrue(F(1, 2) <= DummyRational(1, 2)) 424 self.assertFalse(F(1, 2) <= DummyRational(1, 7)) 425 self.assertFalse(F(1, 2) >= DummyRational(3, 4)) 426 self.assertTrue(F(1, 2) >= DummyRational(1, 2)) 427 self.assertTrue(F(1, 2) >= DummyRational(1, 7)) 428 429 self.assertTrue(DummyRational(1, 2) < F(3, 4)) 430 self.assertFalse(DummyRational(1, 2) < F(1, 2)) 431 self.assertFalse(DummyRational(1, 2) < F(1, 7)) 432 self.assertFalse(DummyRational(1, 2) > F(3, 4)) 433 self.assertFalse(DummyRational(1, 2) > F(1, 2)) 434 self.assertTrue(DummyRational(1, 2) > F(1, 7)) 435 self.assertTrue(DummyRational(1, 2) <= F(3, 4)) 436 self.assertTrue(DummyRational(1, 2) <= F(1, 2)) 437 self.assertFalse(DummyRational(1, 2) <= F(1, 7)) 438 self.assertFalse(DummyRational(1, 2) >= F(3, 4)) 439 self.assertTrue(DummyRational(1, 2) >= F(1, 2)) 440 self.assertTrue(DummyRational(1, 2) >= F(1, 7)) 441 442 def testComparisonsDummyFloat(self): 443 x = DummyFloat(1./3.) 444 y = F(1, 3) 445 self.assertTrue(x != y) 446 self.assertTrue(x < y or x > y) 447 self.assertFalse(x == y) 448 self.assertFalse(x <= y and x >= y) 449 self.assertTrue(y != x) 450 self.assertTrue(y < x or y > x) 451 self.assertFalse(y == x) 452 self.assertFalse(y <= x and y >= x) 453 454 def testMixedLess(self): 455 self.assertTrue(2 < F(5, 2)) 456 self.assertFalse(2 < F(4, 2)) 457 self.assertTrue(F(5, 2) < 3) 458 self.assertFalse(F(4, 2) < 2) 459 460 self.assertTrue(F(1, 2) < 0.6) 461 self.assertFalse(F(1, 2) < 0.4) 462 self.assertTrue(0.4 < F(1, 2)) 463 self.assertFalse(0.5 < F(1, 2)) 464 465 self.assertFalse(float('inf') < F(1, 2)) 466 self.assertTrue(float('-inf') < F(0, 10)) 467 self.assertFalse(float('nan') < F(-3, 7)) 468 self.assertTrue(F(1, 2) < float('inf')) 469 self.assertFalse(F(17, 12) < float('-inf')) 470 self.assertFalse(F(144, -89) < float('nan')) 471 472 def testMixedLessEqual(self): 473 self.assertTrue(0.5 <= F(1, 2)) 474 self.assertFalse(0.6 <= F(1, 2)) 475 self.assertTrue(F(1, 2) <= 0.5) 476 self.assertFalse(F(1, 2) <= 0.4) 477 self.assertTrue(2 <= F(4, 2)) 478 self.assertFalse(2 <= F(3, 2)) 479 self.assertTrue(F(4, 2) <= 2) 480 self.assertFalse(F(5, 2) <= 2) 481 482 self.assertFalse(float('inf') <= F(1, 2)) 483 self.assertTrue(float('-inf') <= F(0, 10)) 484 self.assertFalse(float('nan') <= F(-3, 7)) 485 self.assertTrue(F(1, 2) <= float('inf')) 486 self.assertFalse(F(17, 12) <= float('-inf')) 487 self.assertFalse(F(144, -89) <= float('nan')) 488 489 def testBigFloatComparisons(self): 490 # Because 10**23 can't be represented exactly as a float: 491 self.assertFalse(F(10**23) == float(10**23)) 492 # The first test demonstrates why these are important. 493 self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1))) 494 self.assertTrue(1e23 < F(math.trunc(1e23) + 1)) 495 self.assertFalse(1e23 <= F(math.trunc(1e23) - 1)) 496 self.assertTrue(1e23 > F(math.trunc(1e23) - 1)) 497 self.assertFalse(1e23 >= F(math.trunc(1e23) + 1)) 498 499 def testBigComplexComparisons(self): 500 self.assertFalse(F(10**23) == complex(10**23)) 501 self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23)) 502 self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23)) 503 504 x = F(3, 8) 505 z = complex(0.375, 0.0) 506 w = complex(0.375, 0.2) 507 self.assertTrue(x == z) 508 self.assertFalse(x != z) 509 self.assertFalse(x == w) 510 self.assertTrue(x != w) 511 for op in operator.lt, operator.le, operator.gt, operator.ge: 512 self.assertRaises(TypeError, op, x, z) 513 self.assertRaises(TypeError, op, z, x) 514 self.assertRaises(TypeError, op, x, w) 515 self.assertRaises(TypeError, op, w, x) 516 517 def testMixedEqual(self): 518 self.assertTrue(0.5 == F(1, 2)) 519 self.assertFalse(0.6 == F(1, 2)) 520 self.assertTrue(F(1, 2) == 0.5) 521 self.assertFalse(F(1, 2) == 0.4) 522 self.assertTrue(2 == F(4, 2)) 523 self.assertFalse(2 == F(3, 2)) 524 self.assertTrue(F(4, 2) == 2) 525 self.assertFalse(F(5, 2) == 2) 526 self.assertFalse(F(5, 2) == float('nan')) 527 self.assertFalse(float('nan') == F(3, 7)) 528 self.assertFalse(F(5, 2) == float('inf')) 529 self.assertFalse(float('-inf') == F(2, 5)) 530 531 def testStringification(self): 532 self.assertEqual("Fraction(7, 3)", repr(F(7, 3))) 533 self.assertEqual("Fraction(6283185307, 2000000000)", 534 repr(F('3.1415926535'))) 535 self.assertEqual("Fraction(-1, 100000000000000000000)", 536 repr(F(1, -10**20))) 537 self.assertEqual("7/3", str(F(7, 3))) 538 self.assertEqual("7", str(F(7, 1))) 539 540 def testHash(self): 541 self.assertEqual(hash(2.5), hash(F(5, 2))) 542 self.assertEqual(hash(10**50), hash(F(10**50))) 543 self.assertNotEqual(hash(float(10**23)), hash(F(10**23))) 544 545 def testApproximatePi(self): 546 # Algorithm borrowed from 547 # http://docs.python.org/lib/decimal-recipes.html 548 three = F(3) 549 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24 550 while abs(s - lasts) > F(1, 10**9): 551 lasts = s 552 n, na = n+na, na+8 553 d, da = d+da, da+32 554 t = (t * n) / d 555 s += t 556 self.assertAlmostEqual(math.pi, s) 557 558 def testApproximateCos1(self): 559 # Algorithm borrowed from 560 # http://docs.python.org/lib/decimal-recipes.html 561 x = F(1) 562 i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1 563 while abs(s - lasts) > F(1, 10**9): 564 lasts = s 565 i += 2 566 fact *= i * (i-1) 567 num *= x * x 568 sign *= -1 569 s += num / fact * sign 570 self.assertAlmostEqual(math.cos(1), s) 571 572 def test_copy_deepcopy_pickle(self): 573 r = F(13, 7) 574 self.assertEqual(r, loads(dumps(r))) 575 self.assertEqual(id(r), id(copy(r))) 576 self.assertEqual(id(r), id(deepcopy(r))) 577 578 def test_slots(self): 579 # Issue 4998 580 r = F(13, 7) 581 self.assertRaises(AttributeError, setattr, r, 'a', 10) 582 583 def test_main(): 584 run_unittest(FractionTest, GcdTest) 585 586 if __name__ == '__main__': 587 test_main() 588