/Lib/test/test_float.py

http://unladen-swallow.googlecode.com/ · Python · 793 lines · 682 code · 80 blank · 31 comment · 38 complexity · 2ffa5657a2b9c1f4cf32d916b9d0639b MD5 · raw file

  1. import unittest, struct
  2. import os
  3. from test import test_support
  4. import math
  5. from math import isinf, isnan, copysign, ldexp
  6. import operator
  7. import random, fractions
  8. INF = float("inf")
  9. NAN = float("nan")
  10. class GeneralFloatCases(unittest.TestCase):
  11. def test_float(self):
  12. self.assertEqual(float(3.14), 3.14)
  13. self.assertEqual(float(314), 314.0)
  14. self.assertEqual(float(314L), 314.0)
  15. self.assertEqual(float(" 3.14 "), 3.14)
  16. self.assertRaises(ValueError, float, " 0x3.1 ")
  17. self.assertRaises(ValueError, float, " -0x3.p-1 ")
  18. self.assertRaises(ValueError, float, " +0x3.p-1 ")
  19. self.assertRaises(ValueError, float, "++3.14")
  20. self.assertRaises(ValueError, float, "+-3.14")
  21. self.assertRaises(ValueError, float, "-+3.14")
  22. self.assertRaises(ValueError, float, "--3.14")
  23. if test_support.have_unicode:
  24. self.assertEqual(float(unicode(" 3.14 ")), 3.14)
  25. self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
  26. # Implementation limitation in PyFloat_FromString()
  27. self.assertRaises(ValueError, float, unicode("1"*10000))
  28. @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
  29. def test_float_with_comma(self):
  30. # set locale to something that doesn't use '.' for the decimal point
  31. # float must not accept the locale specific decimal point but
  32. # it still has to accept the normal python syntac
  33. import locale
  34. if not locale.localeconv()['decimal_point'] == ',':
  35. return
  36. self.assertEqual(float(" 3.14 "), 3.14)
  37. self.assertEqual(float("+3.14 "), 3.14)
  38. self.assertEqual(float("-3.14 "), -3.14)
  39. self.assertEqual(float(".14 "), .14)
  40. self.assertEqual(float("3. "), 3.0)
  41. self.assertEqual(float("3.e3 "), 3000.0)
  42. self.assertEqual(float("3.2e3 "), 3200.0)
  43. self.assertEqual(float("2.5e-1 "), 0.25)
  44. self.assertEqual(float("5e-1"), 0.5)
  45. self.assertRaises(ValueError, float, " 3,14 ")
  46. self.assertRaises(ValueError, float, " +3,14 ")
  47. self.assertRaises(ValueError, float, " -3,14 ")
  48. self.assertRaises(ValueError, float, " 0x3.1 ")
  49. self.assertRaises(ValueError, float, " -0x3.p-1 ")
  50. self.assertRaises(ValueError, float, " +0x3.p-1 ")
  51. self.assertEqual(float(" 25.e-1 "), 2.5)
  52. self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
  53. def test_floatconversion(self):
  54. # Make sure that calls to __float__() work properly
  55. class Foo0:
  56. def __float__(self):
  57. return 42.
  58. class Foo1(object):
  59. def __float__(self):
  60. return 42.
  61. class Foo2(float):
  62. def __float__(self):
  63. return 42.
  64. class Foo3(float):
  65. def __new__(cls, value=0.):
  66. return float.__new__(cls, 2*value)
  67. def __float__(self):
  68. return self
  69. class Foo4(float):
  70. def __float__(self):
  71. return 42
  72. # Issue 5759: __float__ not called on str subclasses (though it is on
  73. # unicode subclasses).
  74. class FooStr(str):
  75. def __float__(self):
  76. return float(str(self)) + 1
  77. class FooUnicode(unicode):
  78. def __float__(self):
  79. return float(unicode(self)) + 1
  80. self.assertAlmostEqual(float(Foo0()), 42.)
  81. self.assertAlmostEqual(float(Foo1()), 42.)
  82. self.assertAlmostEqual(float(Foo2()), 42.)
  83. self.assertAlmostEqual(float(Foo3(21)), 42.)
  84. self.assertRaises(TypeError, float, Foo4(42))
  85. self.assertAlmostEqual(float(FooUnicode('8')), 9.)
  86. self.assertAlmostEqual(float(FooStr('8')), 9.)
  87. def test_floatasratio(self):
  88. for f, ratio in [
  89. (0.875, (7, 8)),
  90. (-0.875, (-7, 8)),
  91. (0.0, (0, 1)),
  92. (11.5, (23, 2)),
  93. ]:
  94. self.assertEqual(f.as_integer_ratio(), ratio)
  95. for i in range(10000):
  96. f = random.random()
  97. f *= 10 ** random.randint(-100, 100)
  98. n, d = f.as_integer_ratio()
  99. self.assertEqual(float(n).__truediv__(d), f)
  100. R = fractions.Fraction
  101. self.assertEqual(R(0, 1),
  102. R(*float(0.0).as_integer_ratio()))
  103. self.assertEqual(R(5, 2),
  104. R(*float(2.5).as_integer_ratio()))
  105. self.assertEqual(R(1, 2),
  106. R(*float(0.5).as_integer_ratio()))
  107. self.assertEqual(R(4728779608739021, 2251799813685248),
  108. R(*float(2.1).as_integer_ratio()))
  109. self.assertEqual(R(-4728779608739021, 2251799813685248),
  110. R(*float(-2.1).as_integer_ratio()))
  111. self.assertEqual(R(-2100, 1),
  112. R(*float(-2100.0).as_integer_ratio()))
  113. self.assertRaises(OverflowError, float('inf').as_integer_ratio)
  114. self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
  115. self.assertRaises(ValueError, float('nan').as_integer_ratio)
  116. class FormatFunctionsTestCase(unittest.TestCase):
  117. def setUp(self):
  118. self.save_formats = {'double':float.__getformat__('double'),
  119. 'float':float.__getformat__('float')}
  120. def tearDown(self):
  121. float.__setformat__('double', self.save_formats['double'])
  122. float.__setformat__('float', self.save_formats['float'])
  123. def test_getformat(self):
  124. self.assert_(float.__getformat__('double') in
  125. ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
  126. self.assert_(float.__getformat__('float') in
  127. ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
  128. self.assertRaises(ValueError, float.__getformat__, 'chicken')
  129. self.assertRaises(TypeError, float.__getformat__, 1)
  130. def test_setformat(self):
  131. for t in 'double', 'float':
  132. float.__setformat__(t, 'unknown')
  133. if self.save_formats[t] == 'IEEE, big-endian':
  134. self.assertRaises(ValueError, float.__setformat__,
  135. t, 'IEEE, little-endian')
  136. elif self.save_formats[t] == 'IEEE, little-endian':
  137. self.assertRaises(ValueError, float.__setformat__,
  138. t, 'IEEE, big-endian')
  139. else:
  140. self.assertRaises(ValueError, float.__setformat__,
  141. t, 'IEEE, big-endian')
  142. self.assertRaises(ValueError, float.__setformat__,
  143. t, 'IEEE, little-endian')
  144. self.assertRaises(ValueError, float.__setformat__,
  145. t, 'chicken')
  146. self.assertRaises(ValueError, float.__setformat__,
  147. 'chicken', 'unknown')
  148. BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
  149. LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
  150. BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
  151. LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
  152. BE_FLOAT_INF = '\x7f\x80\x00\x00'
  153. LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
  154. BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
  155. LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
  156. # on non-IEEE platforms, attempting to unpack a bit pattern
  157. # representing an infinity or a NaN should raise an exception.
  158. class UnknownFormatTestCase(unittest.TestCase):
  159. def setUp(self):
  160. self.save_formats = {'double':float.__getformat__('double'),
  161. 'float':float.__getformat__('float')}
  162. float.__setformat__('double', 'unknown')
  163. float.__setformat__('float', 'unknown')
  164. def tearDown(self):
  165. float.__setformat__('double', self.save_formats['double'])
  166. float.__setformat__('float', self.save_formats['float'])
  167. def test_double_specials_dont_unpack(self):
  168. for fmt, data in [('>d', BE_DOUBLE_INF),
  169. ('>d', BE_DOUBLE_NAN),
  170. ('<d', LE_DOUBLE_INF),
  171. ('<d', LE_DOUBLE_NAN)]:
  172. self.assertRaises(ValueError, struct.unpack, fmt, data)
  173. def test_float_specials_dont_unpack(self):
  174. for fmt, data in [('>f', BE_FLOAT_INF),
  175. ('>f', BE_FLOAT_NAN),
  176. ('<f', LE_FLOAT_INF),
  177. ('<f', LE_FLOAT_NAN)]:
  178. self.assertRaises(ValueError, struct.unpack, fmt, data)
  179. # on an IEEE platform, all we guarantee is that bit patterns
  180. # representing infinities or NaNs do not raise an exception; all else
  181. # is accident (today).
  182. # let's also try to guarantee that -0.0 and 0.0 don't get confused.
  183. class IEEEFormatTestCase(unittest.TestCase):
  184. if float.__getformat__("double").startswith("IEEE"):
  185. def test_double_specials_do_unpack(self):
  186. for fmt, data in [('>d', BE_DOUBLE_INF),
  187. ('>d', BE_DOUBLE_NAN),
  188. ('<d', LE_DOUBLE_INF),
  189. ('<d', LE_DOUBLE_NAN)]:
  190. struct.unpack(fmt, data)
  191. if float.__getformat__("float").startswith("IEEE"):
  192. def test_float_specials_do_unpack(self):
  193. for fmt, data in [('>f', BE_FLOAT_INF),
  194. ('>f', BE_FLOAT_NAN),
  195. ('<f', LE_FLOAT_INF),
  196. ('<f', LE_FLOAT_NAN)]:
  197. struct.unpack(fmt, data)
  198. if float.__getformat__("double").startswith("IEEE"):
  199. def test_negative_zero(self):
  200. import math
  201. def pos_pos():
  202. return 0.0, math.atan2(0.0, -1)
  203. def pos_neg():
  204. return 0.0, math.atan2(-0.0, -1)
  205. def neg_pos():
  206. return -0.0, math.atan2(0.0, -1)
  207. def neg_neg():
  208. return -0.0, math.atan2(-0.0, -1)
  209. self.assertEquals(pos_pos(), neg_pos())
  210. self.assertEquals(pos_neg(), neg_neg())
  211. if float.__getformat__("double").startswith("IEEE"):
  212. def test_underflow_sign(self):
  213. import math
  214. # check that -1e-1000 gives -0.0, not 0.0
  215. self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
  216. self.assertEquals(math.atan2(float('-1e-1000'), -1),
  217. math.atan2(-0.0, -1))
  218. class ReprTestCase(unittest.TestCase):
  219. def test_repr(self):
  220. floats_file = open(os.path.join(os.path.split(__file__)[0],
  221. 'floating_points.txt'))
  222. for line in floats_file:
  223. line = line.strip()
  224. if not line or line.startswith('#'):
  225. continue
  226. v = eval(line)
  227. self.assertEqual(v, eval(repr(v)))
  228. floats_file.close()
  229. # Beginning with Python 2.6 float has cross platform compatible
  230. # ways to create and represent inf and nan
  231. class InfNanTest(unittest.TestCase):
  232. def test_inf_from_str(self):
  233. self.assert_(isinf(float("inf")))
  234. self.assert_(isinf(float("+inf")))
  235. self.assert_(isinf(float("-inf")))
  236. self.assert_(isinf(float("infinity")))
  237. self.assert_(isinf(float("+infinity")))
  238. self.assert_(isinf(float("-infinity")))
  239. self.assertEqual(repr(float("inf")), "inf")
  240. self.assertEqual(repr(float("+inf")), "inf")
  241. self.assertEqual(repr(float("-inf")), "-inf")
  242. self.assertEqual(repr(float("infinity")), "inf")
  243. self.assertEqual(repr(float("+infinity")), "inf")
  244. self.assertEqual(repr(float("-infinity")), "-inf")
  245. self.assertEqual(repr(float("INF")), "inf")
  246. self.assertEqual(repr(float("+Inf")), "inf")
  247. self.assertEqual(repr(float("-iNF")), "-inf")
  248. self.assertEqual(repr(float("Infinity")), "inf")
  249. self.assertEqual(repr(float("+iNfInItY")), "inf")
  250. self.assertEqual(repr(float("-INFINITY")), "-inf")
  251. self.assertEqual(str(float("inf")), "inf")
  252. self.assertEqual(str(float("+inf")), "inf")
  253. self.assertEqual(str(float("-inf")), "-inf")
  254. self.assertEqual(str(float("infinity")), "inf")
  255. self.assertEqual(str(float("+infinity")), "inf")
  256. self.assertEqual(str(float("-infinity")), "-inf")
  257. self.assertRaises(ValueError, float, "info")
  258. self.assertRaises(ValueError, float, "+info")
  259. self.assertRaises(ValueError, float, "-info")
  260. self.assertRaises(ValueError, float, "in")
  261. self.assertRaises(ValueError, float, "+in")
  262. self.assertRaises(ValueError, float, "-in")
  263. self.assertRaises(ValueError, float, "infinit")
  264. self.assertRaises(ValueError, float, "+Infin")
  265. self.assertRaises(ValueError, float, "-INFI")
  266. self.assertRaises(ValueError, float, "infinitys")
  267. def test_inf_as_str(self):
  268. self.assertEqual(repr(1e300 * 1e300), "inf")
  269. self.assertEqual(repr(-1e300 * 1e300), "-inf")
  270. self.assertEqual(str(1e300 * 1e300), "inf")
  271. self.assertEqual(str(-1e300 * 1e300), "-inf")
  272. def test_nan_from_str(self):
  273. self.assert_(isnan(float("nan")))
  274. self.assert_(isnan(float("+nan")))
  275. self.assert_(isnan(float("-nan")))
  276. self.assertEqual(repr(float("nan")), "nan")
  277. self.assertEqual(repr(float("+nan")), "nan")
  278. self.assertEqual(repr(float("-nan")), "nan")
  279. self.assertEqual(repr(float("NAN")), "nan")
  280. self.assertEqual(repr(float("+NAn")), "nan")
  281. self.assertEqual(repr(float("-NaN")), "nan")
  282. self.assertEqual(str(float("nan")), "nan")
  283. self.assertEqual(str(float("+nan")), "nan")
  284. self.assertEqual(str(float("-nan")), "nan")
  285. self.assertRaises(ValueError, float, "nana")
  286. self.assertRaises(ValueError, float, "+nana")
  287. self.assertRaises(ValueError, float, "-nana")
  288. self.assertRaises(ValueError, float, "na")
  289. self.assertRaises(ValueError, float, "+na")
  290. self.assertRaises(ValueError, float, "-na")
  291. def test_nan_as_str(self):
  292. self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
  293. self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
  294. self.assertEqual(str(1e300 * 1e300 * 0), "nan")
  295. self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
  296. def notest_float_nan(self):
  297. self.assert_(NAN.is_nan())
  298. self.failIf(INF.is_nan())
  299. self.failIf((0.).is_nan())
  300. def notest_float_inf(self):
  301. self.assert_(INF.is_inf())
  302. self.failIf(NAN.is_inf())
  303. self.failIf((0.).is_inf())
  304. fromHex = float.fromhex
  305. toHex = float.hex
  306. class HexFloatTestCase(unittest.TestCase):
  307. MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
  308. MIN = fromHex('0x1p-1022') # min normal
  309. TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
  310. EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
  311. def identical(self, x, y):
  312. # check that floats x and y are identical, or that both
  313. # are NaNs
  314. if isnan(x) or isnan(y):
  315. if isnan(x) == isnan(y):
  316. return
  317. elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
  318. return
  319. self.fail('%r not identical to %r' % (x, y))
  320. def test_ends(self):
  321. self.identical(self.MIN, ldexp(1.0, -1022))
  322. self.identical(self.TINY, ldexp(1.0, -1074))
  323. self.identical(self.EPS, ldexp(1.0, -52))
  324. self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
  325. def test_invalid_inputs(self):
  326. invalid_inputs = [
  327. 'infi', # misspelt infinities and nans
  328. '-Infinit',
  329. '++inf',
  330. '-+Inf',
  331. '--nan',
  332. '+-NaN',
  333. 'snan',
  334. 'NaNs',
  335. 'nna',
  336. 'an',
  337. 'nf',
  338. 'nfinity',
  339. 'inity',
  340. 'iinity',
  341. '0xnan',
  342. '',
  343. ' ',
  344. 'x1.0p0',
  345. '0xX1.0p0',
  346. '+ 0x1.0p0', # internal whitespace
  347. '- 0x1.0p0',
  348. '0 x1.0p0',
  349. '0x 1.0p0',
  350. '0x1 2.0p0',
  351. '+0x1 .0p0',
  352. '0x1. 0p0',
  353. '-0x1.0 1p0',
  354. '-0x1.0 p0',
  355. '+0x1.0p +0',
  356. '0x1.0p -0',
  357. '0x1.0p 0',
  358. '+0x1.0p+ 0',
  359. '-0x1.0p- 0',
  360. '++0x1.0p-0', # double signs
  361. '--0x1.0p0',
  362. '+-0x1.0p+0',
  363. '-+0x1.0p0',
  364. '0x1.0p++0',
  365. '+0x1.0p+-0',
  366. '-0x1.0p-+0',
  367. '0x1.0p--0',
  368. '0x1.0.p0',
  369. '0x.p0', # no hex digits before or after point
  370. '0x1,p0', # wrong decimal point character
  371. '0x1pa',
  372. u'0x1p\uff10', # fullwidth Unicode digits
  373. u'\uff10x1p0',
  374. u'0x\uff11p0',
  375. u'0x1.\uff10p0',
  376. '0x1p0 \n 0x2p0',
  377. '0x1p0\0 0x1p0', # embedded null byte is not end of string
  378. ]
  379. for x in invalid_inputs:
  380. try:
  381. result = fromHex(x)
  382. except ValueError:
  383. pass
  384. else:
  385. self.fail('Expected float.fromhex(%r) to raise ValueError; '
  386. 'got %r instead' % (x, result))
  387. def test_whitespace(self):
  388. value_pairs = [
  389. ('inf', INF),
  390. ('-Infinity', -INF),
  391. ('nan', NAN),
  392. ('1.0', 1.0),
  393. ('-0x.2', -0.125),
  394. ('-0.0', -0.0)
  395. ]
  396. whitespace = [
  397. '',
  398. ' ',
  399. '\t',
  400. '\n',
  401. '\n \t',
  402. '\f',
  403. '\v',
  404. '\r'
  405. ]
  406. for inp, expected in value_pairs:
  407. for lead in whitespace:
  408. for trail in whitespace:
  409. got = fromHex(lead + inp + trail)
  410. self.identical(got, expected)
  411. def test_from_hex(self):
  412. MIN = self.MIN;
  413. MAX = self.MAX;
  414. TINY = self.TINY;
  415. EPS = self.EPS;
  416. # two spellings of infinity, with optional signs; case-insensitive
  417. self.identical(fromHex('inf'), INF)
  418. self.identical(fromHex('+Inf'), INF)
  419. self.identical(fromHex('-INF'), -INF)
  420. self.identical(fromHex('iNf'), INF)
  421. self.identical(fromHex('Infinity'), INF)
  422. self.identical(fromHex('+INFINITY'), INF)
  423. self.identical(fromHex('-infinity'), -INF)
  424. self.identical(fromHex('-iNFiNitY'), -INF)
  425. # nans with optional sign; case insensitive
  426. self.identical(fromHex('nan'), NAN)
  427. self.identical(fromHex('+NaN'), NAN)
  428. self.identical(fromHex('-NaN'), NAN)
  429. self.identical(fromHex('-nAN'), NAN)
  430. # variations in input format
  431. self.identical(fromHex('1'), 1.0)
  432. self.identical(fromHex('+1'), 1.0)
  433. self.identical(fromHex('1.'), 1.0)
  434. self.identical(fromHex('1.0'), 1.0)
  435. self.identical(fromHex('1.0p0'), 1.0)
  436. self.identical(fromHex('01'), 1.0)
  437. self.identical(fromHex('01.'), 1.0)
  438. self.identical(fromHex('0x1'), 1.0)
  439. self.identical(fromHex('0x1.'), 1.0)
  440. self.identical(fromHex('0x1.0'), 1.0)
  441. self.identical(fromHex('+0x1.0'), 1.0)
  442. self.identical(fromHex('0x1p0'), 1.0)
  443. self.identical(fromHex('0X1p0'), 1.0)
  444. self.identical(fromHex('0X1P0'), 1.0)
  445. self.identical(fromHex('0x1P0'), 1.0)
  446. self.identical(fromHex('0x1.p0'), 1.0)
  447. self.identical(fromHex('0x1.0p0'), 1.0)
  448. self.identical(fromHex('0x.1p4'), 1.0)
  449. self.identical(fromHex('0x.1p04'), 1.0)
  450. self.identical(fromHex('0x.1p004'), 1.0)
  451. self.identical(fromHex('0x1p+0'), 1.0)
  452. self.identical(fromHex('0x1P-0'), 1.0)
  453. self.identical(fromHex('+0x1p0'), 1.0)
  454. self.identical(fromHex('0x01p0'), 1.0)
  455. self.identical(fromHex('0x1p00'), 1.0)
  456. self.identical(fromHex(u'0x1p0'), 1.0)
  457. self.identical(fromHex(' 0x1p0 '), 1.0)
  458. self.identical(fromHex('\n 0x1p0'), 1.0)
  459. self.identical(fromHex('0x1p0 \t'), 1.0)
  460. self.identical(fromHex('0xap0'), 10.0)
  461. self.identical(fromHex('0xAp0'), 10.0)
  462. self.identical(fromHex('0xaP0'), 10.0)
  463. self.identical(fromHex('0xAP0'), 10.0)
  464. self.identical(fromHex('0xbep0'), 190.0)
  465. self.identical(fromHex('0xBep0'), 190.0)
  466. self.identical(fromHex('0xbEp0'), 190.0)
  467. self.identical(fromHex('0XBE0P-4'), 190.0)
  468. self.identical(fromHex('0xBEp0'), 190.0)
  469. self.identical(fromHex('0xB.Ep4'), 190.0)
  470. self.identical(fromHex('0x.BEp8'), 190.0)
  471. self.identical(fromHex('0x.0BEp12'), 190.0)
  472. # moving the point around
  473. pi = fromHex('0x1.921fb54442d18p1')
  474. self.identical(fromHex('0x.006487ed5110b46p11'), pi)
  475. self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
  476. self.identical(fromHex('0x.01921fb54442d18p9'), pi)
  477. self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
  478. self.identical(fromHex('0x.06487ed5110b46p7'), pi)
  479. self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
  480. self.identical(fromHex('0x.1921fb54442d18p5'), pi)
  481. self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
  482. self.identical(fromHex('0x.6487ed5110b46p3'), pi)
  483. self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
  484. self.identical(fromHex('0x1.921fb54442d18p1'), pi)
  485. self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
  486. self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
  487. self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
  488. self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
  489. self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
  490. self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
  491. self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
  492. self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
  493. self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
  494. self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
  495. self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
  496. self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
  497. # ...
  498. self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
  499. self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
  500. self.identical(fromHex('0x6487ed5110b46p-49'), pi)
  501. self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
  502. self.identical(fromHex('0x1921fb54442d18p-51'), pi)
  503. self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
  504. self.identical(fromHex('0x6487ed5110b460p-53'), pi)
  505. self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
  506. self.identical(fromHex('0x1921fb54442d180p-55'), pi)
  507. # results that should overflow...
  508. self.assertRaises(OverflowError, fromHex, '-0x1p1024')
  509. self.assertRaises(OverflowError, fromHex, '0x1p+1025')
  510. self.assertRaises(OverflowError, fromHex, '+0X1p1030')
  511. self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
  512. self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
  513. self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
  514. self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
  515. self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
  516. self.assertRaises(OverflowError, fromHex, '0X2p+1023')
  517. self.assertRaises(OverflowError, fromHex, '0x2.p1023')
  518. self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
  519. self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
  520. self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
  521. self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
  522. self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
  523. self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
  524. self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
  525. self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
  526. self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
  527. # ...and those that round to +-max float
  528. self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
  529. self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
  530. self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
  531. # zeros
  532. self.identical(fromHex('0x0p0'), 0.0)
  533. self.identical(fromHex('0x0p1000'), 0.0)
  534. self.identical(fromHex('-0x0p1023'), -0.0)
  535. self.identical(fromHex('0X0p1024'), 0.0)
  536. self.identical(fromHex('-0x0p1025'), -0.0)
  537. self.identical(fromHex('0X0p2000'), 0.0)
  538. self.identical(fromHex('0x0p123456789123456789'), 0.0)
  539. self.identical(fromHex('-0X0p-0'), -0.0)
  540. self.identical(fromHex('-0X0p-1000'), -0.0)
  541. self.identical(fromHex('0x0p-1023'), 0.0)
  542. self.identical(fromHex('-0X0p-1024'), -0.0)
  543. self.identical(fromHex('-0x0p-1025'), -0.0)
  544. self.identical(fromHex('-0x0p-1072'), -0.0)
  545. self.identical(fromHex('0X0p-1073'), 0.0)
  546. self.identical(fromHex('-0x0p-1074'), -0.0)
  547. self.identical(fromHex('0x0p-1075'), 0.0)
  548. self.identical(fromHex('0X0p-1076'), 0.0)
  549. self.identical(fromHex('-0X0p-2000'), -0.0)
  550. self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
  551. # values that should underflow to 0
  552. self.identical(fromHex('0X1p-1075'), 0.0)
  553. self.identical(fromHex('-0X1p-1075'), -0.0)
  554. self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
  555. self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
  556. self.identical(fromHex('-0x1.1p-1075'), -TINY)
  557. self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
  558. # check round-half-even is working correctly near 0 ...
  559. self.identical(fromHex('0x1p-1076'), 0.0)
  560. self.identical(fromHex('0X2p-1076'), 0.0)
  561. self.identical(fromHex('0X3p-1076'), TINY)
  562. self.identical(fromHex('0x4p-1076'), TINY)
  563. self.identical(fromHex('0X5p-1076'), TINY)
  564. self.identical(fromHex('0X6p-1076'), 2*TINY)
  565. self.identical(fromHex('0x7p-1076'), 2*TINY)
  566. self.identical(fromHex('0X8p-1076'), 2*TINY)
  567. self.identical(fromHex('0X9p-1076'), 2*TINY)
  568. self.identical(fromHex('0xap-1076'), 2*TINY)
  569. self.identical(fromHex('0Xbp-1076'), 3*TINY)
  570. self.identical(fromHex('0xcp-1076'), 3*TINY)
  571. self.identical(fromHex('0Xdp-1076'), 3*TINY)
  572. self.identical(fromHex('0Xep-1076'), 4*TINY)
  573. self.identical(fromHex('0xfp-1076'), 4*TINY)
  574. self.identical(fromHex('0x10p-1076'), 4*TINY)
  575. self.identical(fromHex('-0x1p-1076'), -0.0)
  576. self.identical(fromHex('-0X2p-1076'), -0.0)
  577. self.identical(fromHex('-0x3p-1076'), -TINY)
  578. self.identical(fromHex('-0X4p-1076'), -TINY)
  579. self.identical(fromHex('-0x5p-1076'), -TINY)
  580. self.identical(fromHex('-0x6p-1076'), -2*TINY)
  581. self.identical(fromHex('-0X7p-1076'), -2*TINY)
  582. self.identical(fromHex('-0X8p-1076'), -2*TINY)
  583. self.identical(fromHex('-0X9p-1076'), -2*TINY)
  584. self.identical(fromHex('-0Xap-1076'), -2*TINY)
  585. self.identical(fromHex('-0xbp-1076'), -3*TINY)
  586. self.identical(fromHex('-0xcp-1076'), -3*TINY)
  587. self.identical(fromHex('-0Xdp-1076'), -3*TINY)
  588. self.identical(fromHex('-0xep-1076'), -4*TINY)
  589. self.identical(fromHex('-0Xfp-1076'), -4*TINY)
  590. self.identical(fromHex('-0X10p-1076'), -4*TINY)
  591. # ... and near MIN ...
  592. self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
  593. self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
  594. self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
  595. self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
  596. self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
  597. self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
  598. self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
  599. self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
  600. self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
  601. self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
  602. self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
  603. self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
  604. self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
  605. self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
  606. self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
  607. self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
  608. self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
  609. self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
  610. self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
  611. self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
  612. self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
  613. self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
  614. self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
  615. self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
  616. self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
  617. self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
  618. self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
  619. self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
  620. self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
  621. self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
  622. self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
  623. self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
  624. self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
  625. self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
  626. # ... and near 1.0.
  627. self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
  628. self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
  629. self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
  630. self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
  631. self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
  632. self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
  633. self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
  634. self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
  635. self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
  636. self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
  637. self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
  638. self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
  639. self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
  640. self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
  641. self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
  642. self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
  643. self.identical(fromHex('0X1.00000000000000p0'), 1.0)
  644. self.identical(fromHex('0X1.00000000000001p0'), 1.0)
  645. self.identical(fromHex('0x1.00000000000002p0'), 1.0)
  646. self.identical(fromHex('0X1.00000000000003p0'), 1.0)
  647. self.identical(fromHex('0x1.00000000000004p0'), 1.0)
  648. self.identical(fromHex('0X1.00000000000005p0'), 1.0)
  649. self.identical(fromHex('0X1.00000000000006p0'), 1.0)
  650. self.identical(fromHex('0X1.00000000000007p0'), 1.0)
  651. self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
  652. 1.0)
  653. self.identical(fromHex('0x1.00000000000008p0'), 1.0)
  654. self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
  655. 1+EPS)
  656. self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
  657. self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
  658. self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
  659. self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
  660. self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
  661. self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
  662. self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
  663. self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
  664. self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
  665. self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
  666. self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
  667. self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
  668. self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
  669. self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
  670. self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
  671. self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
  672. 1.0+EPS)
  673. self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
  674. self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
  675. 1.0+2*EPS)
  676. self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
  677. self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
  678. self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
  679. self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
  680. self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
  681. self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
  682. self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
  683. self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
  684. def test_roundtrip(self):
  685. def roundtrip(x):
  686. return fromHex(toHex(x))
  687. for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
  688. self.identical(x, roundtrip(x))
  689. self.identical(-x, roundtrip(-x))
  690. # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
  691. import random
  692. for i in xrange(10000):
  693. e = random.randrange(-1200, 1200)
  694. m = random.random()
  695. s = random.choice([1.0, -1.0])
  696. try:
  697. x = s*ldexp(m, e)
  698. except OverflowError:
  699. pass
  700. else:
  701. self.identical(x, fromHex(toHex(x)))
  702. def test_main():
  703. test_support.run_unittest(
  704. GeneralFloatCases,
  705. FormatFunctionsTestCase,
  706. UnknownFormatTestCase,
  707. IEEEFormatTestCase,
  708. ReprTestCase,
  709. InfNanTest,
  710. HexFloatTestCase,
  711. )
  712. if __name__ == '__main__':
  713. test_main()