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