test_fractions.py 34 KB

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