test_fractions.py 24 KB

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