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