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