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