this repo has no description
at trunk 1495 lines 66 kB view raw
1#!/usr/bin/env python3 2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 3# WARNING: This is a temporary copy of code from the cpython library to 4# facilitate bringup. Please file a task for anything you change! 5# flake8: noqa 6# fmt: off 7 8import fractions 9import operator 10import os 11import random 12import sys 13import struct 14import time 15import unittest 16 17from test import support 18from test.test_grammar import (VALID_UNDERSCORE_LITERALS, 19 INVALID_UNDERSCORE_LITERALS) 20from math import isinf, isnan, copysign, ldexp 21 22from test_support import cpython_only 23 24INF = float("inf") 25NAN = float("nan") 26 27have_getformat = hasattr(float, "__getformat__") 28requires_getformat = unittest.skipUnless(have_getformat, 29 "requires __getformat__") 30# TODO(T89800492) 31requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__") 32 and sys.implementation.name != "skybison", 33 "requires __setformat__") 34 35#locate file with float format test values 36test_dir = os.path.dirname(__file__) or os.curdir 37format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt') 38 39class FloatSubclass(float): 40 pass 41 42class OtherFloatSubclass(float): 43 pass 44 45class GeneralFloatCases(unittest.TestCase): 46 # TODO(T89786301) 47 @cpython_only 48 def test_float(self): 49 self.assertEqual(float(3.14), 3.14) 50 self.assertEqual(float(314), 314.0) 51 self.assertEqual(float(" 3.14 "), 3.14) 52 self.assertRaises(ValueError, float, " 0x3.1 ") 53 self.assertRaises(ValueError, float, " -0x3.p-1 ") 54 self.assertRaises(ValueError, float, " +0x3.p-1 ") 55 self.assertRaises(ValueError, float, "++3.14") 56 self.assertRaises(ValueError, float, "+-3.14") 57 self.assertRaises(ValueError, float, "-+3.14") 58 self.assertRaises(ValueError, float, "--3.14") 59 self.assertRaises(ValueError, float, ".nan") 60 self.assertRaises(ValueError, float, "+.inf") 61 self.assertRaises(ValueError, float, ".") 62 self.assertRaises(ValueError, float, "-.") 63 self.assertRaises(TypeError, float, {}) 64 self.assertRaisesRegex(TypeError, "not 'dict'", float, {}) 65 # Lone surrogate 66 self.assertRaises(ValueError, float, '\uD8F0') 67 # check that we don't accept alternate exponent markers 68 self.assertRaises(ValueError, float, "-1.7d29") 69 self.assertRaises(ValueError, float, "3D-14") 70 self.assertEqual(float(" \u0663.\u0661\u0664 "), 3.14) 71 # TODO(T89787952): Pyro syntax error 72 # self.assertEqual(float("\N{EM SPACE}3.14\N{EN SPACE}"), 3.14) 73 # extra long strings should not be a problem 74 float(b'.' + b'1'*1000) 75 float('.' + '1'*1000) 76 # Invalid unicode string 77 # See bpo-34087 78 self.assertRaises(ValueError, float, '\u3053\u3093\u306b\u3061\u306f') 79 80 # TODO(T89786448) 81 @cpython_only 82 def test_underscores(self): 83 for lit in VALID_UNDERSCORE_LITERALS: 84 if not any(ch in lit for ch in 'jJxXoObB'): 85 self.assertEqual(float(lit), eval(lit)) 86 self.assertEqual(float(lit), float(lit.replace('_', ''))) 87 for lit in INVALID_UNDERSCORE_LITERALS: 88 if lit in ('0_7', '09_99'): # octals are not recognized here 89 continue 90 if not any(ch in lit for ch in 'jJxXoObB'): 91 self.assertRaises(ValueError, float, lit) 92 # Additional test cases; nan and inf are never valid as literals, 93 # only in the float() constructor, but we don't allow underscores 94 # in or around them. 95 self.assertRaises(ValueError, float, '_NaN') 96 self.assertRaises(ValueError, float, 'Na_N') 97 self.assertRaises(ValueError, float, 'IN_F') 98 self.assertRaises(ValueError, float, '-_INF') 99 self.assertRaises(ValueError, float, '-INF_') 100 # Check that we handle bytes values correctly. 101 self.assertRaises(ValueError, float, b'0_.\xff9') 102 103 # TODO(T89801927): [pyro] Implement float_new_from_byteslike_func 104 @cpython_only 105 def test_non_numeric_input_types(self): 106 # Test possible non-numeric types for the argument x, including 107 # subclasses of the explicitly documented accepted types. 108 class CustomStr(str): pass 109 class CustomBytes(bytes): pass 110 class CustomByteArray(bytearray): pass 111 112 factories = [ 113 bytes, 114 bytearray, 115 lambda b: CustomStr(b.decode()), 116 CustomBytes, 117 CustomByteArray, 118 memoryview, 119 ] 120 try: 121 from array import array 122 except ImportError: 123 pass 124 else: 125 factories.append(lambda b: array('B', b)) 126 127 for f in factories: 128 x = f(b" 3.14 ") 129 with self.subTest(type(x)): 130 self.assertEqual(float(x), 3.14) 131 with self.assertRaisesRegex(ValueError, "could not convert"): 132 float(f(b'A' * 0x10)) 133 134 # TODO(T89801927): [pyro] Implement float_new_from_byteslike_func 135 @cpython_only 136 def test_float_memoryview(self): 137 self.assertEqual(float(memoryview(b'12.3')[1:4]), 2.3) 138 self.assertEqual(float(memoryview(b'12.3\x00')[1:4]), 2.3) 139 self.assertEqual(float(memoryview(b'12.3 ')[1:4]), 2.3) 140 self.assertEqual(float(memoryview(b'12.3A')[1:4]), 2.3) 141 self.assertEqual(float(memoryview(b'12.34')[1:4]), 2.3) 142 143 # TODO(T89786553) 144 @cpython_only 145 def test_error_message(self): 146 def check(s): 147 with self.assertRaises(ValueError, msg='float(%r)' % (s,)) as cm: 148 float(s) 149 self.assertEqual(str(cm.exception), 150 'could not convert string to float: %r' % (s,)) 151 152 check('\xbd') 153 check('123\xbd') 154 check(' 123 456 ') 155 check(b' 123 456 ') 156 157 # non-ascii digits (error came from non-digit '!') 158 check('\u0663\u0661\u0664!') 159 # embedded NUL 160 check('123\x00') 161 check('123\x00 245') 162 check('123\x00245') 163 # byte string with embedded NUL 164 check(b'123\x00') 165 # non-UTF-8 byte string 166 check(b'123\xa0') 167 168 # TODO(T89786632) 169 @cpython_only 170 @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE') 171 def test_float_with_comma(self): 172 # set locale to something that doesn't use '.' for the decimal point 173 # float must not accept the locale specific decimal point but 174 # it still has to accept the normal python syntax 175 import locale 176 if not locale.localeconv()['decimal_point'] == ',': 177 self.skipTest('decimal_point is not ","') 178 179 self.assertEqual(float(" 3.14 "), 3.14) 180 self.assertEqual(float("+3.14 "), 3.14) 181 self.assertEqual(float("-3.14 "), -3.14) 182 self.assertEqual(float(".14 "), .14) 183 self.assertEqual(float("3. "), 3.0) 184 self.assertEqual(float("3.e3 "), 3000.0) 185 self.assertEqual(float("3.2e3 "), 3200.0) 186 self.assertEqual(float("2.5e-1 "), 0.25) 187 self.assertEqual(float("5e-1"), 0.5) 188 self.assertRaises(ValueError, float, " 3,14 ") 189 self.assertRaises(ValueError, float, " +3,14 ") 190 self.assertRaises(ValueError, float, " -3,14 ") 191 self.assertRaises(ValueError, float, " 0x3.1 ") 192 self.assertRaises(ValueError, float, " -0x3.p-1 ") 193 self.assertRaises(ValueError, float, " +0x3.p-1 ") 194 self.assertEqual(float(" 25.e-1 "), 2.5) 195 self.assertAlmostEqual(float(" .25e-1 "), .025) 196 197 # TODO(T89786859) 198 @cpython_only 199 def test_floatconversion(self): 200 # Make sure that calls to __float__() work properly 201 class Foo1(object): 202 def __float__(self): 203 return 42. 204 205 class Foo2(float): 206 def __float__(self): 207 return 42. 208 209 class Foo3(float): 210 def __new__(cls, value=0.): 211 return float.__new__(cls, 2*value) 212 213 def __float__(self): 214 return self 215 216 class Foo4(float): 217 def __float__(self): 218 return 42 219 220 # Issue 5759: __float__ not called on str subclasses (though it is on 221 # unicode subclasses). 222 class FooStr(str): 223 def __float__(self): 224 return float(str(self)) + 1 225 226 self.assertEqual(float(Foo1()), 42.) 227 self.assertEqual(float(Foo2()), 42.) 228 with self.assertWarns(DeprecationWarning): 229 self.assertEqual(float(Foo3(21)), 42.) 230 self.assertRaises(TypeError, float, Foo4(42)) 231 self.assertEqual(float(FooStr('8')), 9.) 232 233 class Foo5: 234 def __float__(self): 235 return "" 236 self.assertRaises(TypeError, time.sleep, Foo5()) 237 238 # Issue #24731 239 class F: 240 def __float__(self): 241 return OtherFloatSubclass(42.) 242 with self.assertWarns(DeprecationWarning): 243 self.assertEqual(float(F()), 42.) 244 with self.assertWarns(DeprecationWarning): 245 self.assertIs(type(float(F())), float) 246 with self.assertWarns(DeprecationWarning): 247 self.assertEqual(FloatSubclass(F()), 42.) 248 with self.assertWarns(DeprecationWarning): 249 self.assertIs(type(FloatSubclass(F())), FloatSubclass) 250 251 class MyIndex: 252 def __init__(self, value): 253 self.value = value 254 def __index__(self): 255 return self.value 256 257 self.assertEqual(float(MyIndex(42)), 42.0) 258 self.assertRaises(OverflowError, float, MyIndex(2**2000)) 259 260 class MyInt: 261 def __int__(self): 262 return 42 263 264 self.assertRaises(TypeError, float, MyInt()) 265 266 def test_keyword_args(self): 267 with self.assertRaisesRegex(TypeError, 'keyword argument'): 268 float(x='3.14') 269 270 def test_is_integer(self): 271 self.assertFalse((1.1).is_integer()) 272 self.assertTrue((1.).is_integer()) 273 self.assertFalse(float("nan").is_integer()) 274 self.assertFalse(float("inf").is_integer()) 275 276 def test_floatasratio(self): 277 for f, ratio in [ 278 (0.875, (7, 8)), 279 (-0.875, (-7, 8)), 280 (0.0, (0, 1)), 281 (11.5, (23, 2)), 282 ]: 283 self.assertEqual(f.as_integer_ratio(), ratio) 284 285 for i in range(10000): 286 f = random.random() 287 f *= 10 ** random.randint(-100, 100) 288 n, d = f.as_integer_ratio() 289 self.assertEqual(float(n).__truediv__(d), f) 290 291 R = fractions.Fraction 292 self.assertEqual(R(0, 1), 293 R(*float(0.0).as_integer_ratio())) 294 self.assertEqual(R(5, 2), 295 R(*float(2.5).as_integer_ratio())) 296 self.assertEqual(R(1, 2), 297 R(*float(0.5).as_integer_ratio())) 298 self.assertEqual(R(4728779608739021, 2251799813685248), 299 R(*float(2.1).as_integer_ratio())) 300 self.assertEqual(R(-4728779608739021, 2251799813685248), 301 R(*float(-2.1).as_integer_ratio())) 302 self.assertEqual(R(-2100, 1), 303 R(*float(-2100.0).as_integer_ratio())) 304 305 self.assertRaises(OverflowError, float('inf').as_integer_ratio) 306 self.assertRaises(OverflowError, float('-inf').as_integer_ratio) 307 self.assertRaises(ValueError, float('nan').as_integer_ratio) 308 309 def test_float_containment(self): 310 floats = (INF, -INF, 0.0, 1.0, NAN) 311 for f in floats: 312 self.assertIn(f, [f]) 313 self.assertIn(f, (f,)) 314 self.assertIn(f, {f}) 315 self.assertIn(f, {f: None}) 316 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f) 317 self.assertIn(f, floats) 318 319 for f in floats: 320 # nonidentical containers, same type, same contents 321 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f)) 322 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f)) 323 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f)) 324 self.assertTrue({f : None} == {f: None}, "{%r : None} != " 325 "{%r : None}" % (f, f)) 326 327 # identical containers 328 l, t, s, d = [f], (f,), {f}, {f: None} 329 self.assertTrue(l == l, "[%r] not equal to itself" % f) 330 self.assertTrue(t == t, "(%r,) not equal to itself" % f) 331 self.assertTrue(s == s, "{%r} not equal to itself" % f) 332 self.assertTrue(d == d, "{%r : None} not equal to itself" % f) 333 334 def assertEqualAndEqualSign(self, a, b): 335 # fail unless a == b and a and b have the same sign bit; 336 # the only difference from assertEqual is that this test 337 # distinguishes -0.0 and 0.0. 338 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b))) 339 340 @support.requires_IEEE_754 341 def test_float_mod(self): 342 # Check behaviour of % operator for IEEE 754 special cases. 343 # In particular, check signs of zeros. 344 mod = operator.mod 345 346 self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0) 347 self.assertEqualAndEqualSign(mod(-1e-100, 1.0), 1.0) 348 self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0) 349 self.assertEqualAndEqualSign(mod(0.0, 1.0), 0.0) 350 self.assertEqualAndEqualSign(mod(1e-100, 1.0), 1e-100) 351 self.assertEqualAndEqualSign(mod(1.0, 1.0), 0.0) 352 353 self.assertEqualAndEqualSign(mod(-1.0, -1.0), -0.0) 354 self.assertEqualAndEqualSign(mod(-1e-100, -1.0), -1e-100) 355 self.assertEqualAndEqualSign(mod(-0.0, -1.0), -0.0) 356 self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0) 357 self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0) 358 self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0) 359 360 # TODO(T89786982) 361 @cpython_only 362 @support.requires_IEEE_754 363 def test_float_pow(self): 364 # test builtin pow and ** operator for IEEE 754 special cases. 365 # Special cases taken from section F.9.4.4 of the C99 specification 366 367 for pow_op in pow, operator.pow: 368 # x**NAN is NAN for any x except 1 369 self.assertTrue(isnan(pow_op(-INF, NAN))) 370 self.assertTrue(isnan(pow_op(-2.0, NAN))) 371 self.assertTrue(isnan(pow_op(-1.0, NAN))) 372 self.assertTrue(isnan(pow_op(-0.5, NAN))) 373 self.assertTrue(isnan(pow_op(-0.0, NAN))) 374 self.assertTrue(isnan(pow_op(0.0, NAN))) 375 self.assertTrue(isnan(pow_op(0.5, NAN))) 376 self.assertTrue(isnan(pow_op(2.0, NAN))) 377 self.assertTrue(isnan(pow_op(INF, NAN))) 378 self.assertTrue(isnan(pow_op(NAN, NAN))) 379 380 # NAN**y is NAN for any y except +-0 381 self.assertTrue(isnan(pow_op(NAN, -INF))) 382 self.assertTrue(isnan(pow_op(NAN, -2.0))) 383 self.assertTrue(isnan(pow_op(NAN, -1.0))) 384 self.assertTrue(isnan(pow_op(NAN, -0.5))) 385 self.assertTrue(isnan(pow_op(NAN, 0.5))) 386 self.assertTrue(isnan(pow_op(NAN, 1.0))) 387 self.assertTrue(isnan(pow_op(NAN, 2.0))) 388 self.assertTrue(isnan(pow_op(NAN, INF))) 389 390 # (+-0)**y raises ZeroDivisionError for y a negative odd integer 391 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0) 392 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0) 393 394 # (+-0)**y raises ZeroDivisionError for y finite and negative 395 # but not an odd integer 396 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0) 397 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5) 398 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0) 399 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5) 400 401 # (+-0)**y is +-0 for y a positive odd integer 402 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0) 403 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0) 404 405 # (+-0)**y is 0 for y finite and positive but not an odd integer 406 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0) 407 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0) 408 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0) 409 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0) 410 411 # (-1)**+-inf is 1 412 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0) 413 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0) 414 415 # 1**y is 1 for any y, even if y is an infinity or nan 416 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0) 417 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0) 418 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0) 419 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0) 420 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0) 421 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0) 422 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0) 423 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0) 424 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0) 425 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0) 426 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0) 427 428 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan 429 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0) 430 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0) 431 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0) 432 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0) 433 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0) 434 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0) 435 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0) 436 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0) 437 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0) 438 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0) 439 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0) 440 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0) 441 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0) 442 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0) 443 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0) 444 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0) 445 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0) 446 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0) 447 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0) 448 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0) 449 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0) 450 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0) 451 452 # x**y defers to complex pow for finite negative x and 453 # non-integral y. 454 self.assertEqual(type(pow_op(-2.0, -0.5)), complex) 455 self.assertEqual(type(pow_op(-2.0, 0.5)), complex) 456 self.assertEqual(type(pow_op(-1.0, -0.5)), complex) 457 self.assertEqual(type(pow_op(-1.0, 0.5)), complex) 458 self.assertEqual(type(pow_op(-0.5, -0.5)), complex) 459 self.assertEqual(type(pow_op(-0.5, 0.5)), complex) 460 461 # x**-INF is INF for abs(x) < 1 462 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF) 463 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF) 464 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF) 465 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF) 466 467 # x**-INF is 0 for abs(x) > 1 468 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0) 469 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0) 470 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0) 471 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0) 472 473 # x**INF is 0 for abs(x) < 1 474 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0) 475 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0) 476 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0) 477 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0) 478 479 # x**INF is INF for abs(x) > 1 480 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF) 481 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF) 482 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF) 483 self.assertEqualAndEqualSign(pow_op(INF, INF), INF) 484 485 # (-INF)**y is -0.0 for y a negative odd integer 486 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0) 487 488 # (-INF)**y is 0.0 for y negative but not an odd integer 489 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0) 490 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0) 491 492 # (-INF)**y is -INF for y a positive odd integer 493 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF) 494 495 # (-INF)**y is INF for y positive but not an odd integer 496 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF) 497 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF) 498 499 # INF**y is INF for y positive 500 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF) 501 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF) 502 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF) 503 504 # INF**y is 0.0 for y negative 505 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0) 506 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0) 507 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0) 508 509 # basic checks not covered by the special cases above 510 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25) 511 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5) 512 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0) 513 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0) 514 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0) 515 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0) 516 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0) 517 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0) 518 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0) 519 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0) 520 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0) 521 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0) 522 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25) 523 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5) 524 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0) 525 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0) 526 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0) 527 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0) 528 529 # 1 ** large and -1 ** large; some libms apparently 530 # have problems with these 531 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0) 532 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0) 533 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0) 534 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0) 535 536 # check sign for results that underflow to 0 537 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0) 538 self.assertEqual(type(pow_op(-2.0, -2000.5)), complex) 539 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0) 540 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0) 541 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0) 542 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0) 543 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0) 544 self.assertEqual(type(pow_op(-0.5, 2000.5)), complex) 545 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0) 546 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0) 547 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0) 548 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0) 549 550 # check we don't raise an exception for subnormal results, 551 # and validate signs. Tests currently disabled, since 552 # they fail on systems where a subnormal result from pow 553 # is flushed to zero (e.g. Debian/ia64.) 554 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315) 555 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315) 556 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315) 557 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315) 558 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315) 559 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315) 560 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315) 561 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315) 562 563 564@requires_setformat 565class FormatFunctionsTestCase(unittest.TestCase): 566 567 def setUp(self): 568 self.save_formats = {'double':float.__getformat__('double'), 569 'float':float.__getformat__('float')} 570 571 def tearDown(self): 572 float.__setformat__('double', self.save_formats['double']) 573 float.__setformat__('float', self.save_formats['float']) 574 575 def test_getformat(self): 576 self.assertIn(float.__getformat__('double'), 577 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian']) 578 self.assertIn(float.__getformat__('float'), 579 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian']) 580 self.assertRaises(ValueError, float.__getformat__, 'chicken') 581 self.assertRaises(TypeError, float.__getformat__, 1) 582 583 def test_setformat(self): 584 for t in 'double', 'float': 585 float.__setformat__(t, 'unknown') 586 if self.save_formats[t] == 'IEEE, big-endian': 587 self.assertRaises(ValueError, float.__setformat__, 588 t, 'IEEE, little-endian') 589 elif self.save_formats[t] == 'IEEE, little-endian': 590 self.assertRaises(ValueError, float.__setformat__, 591 t, 'IEEE, big-endian') 592 else: 593 self.assertRaises(ValueError, float.__setformat__, 594 t, 'IEEE, big-endian') 595 self.assertRaises(ValueError, float.__setformat__, 596 t, 'IEEE, little-endian') 597 self.assertRaises(ValueError, float.__setformat__, 598 t, 'chicken') 599 self.assertRaises(ValueError, float.__setformat__, 600 'chicken', 'unknown') 601 602BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00' 603LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF)) 604BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00' 605LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN)) 606 607BE_FLOAT_INF = b'\x7f\x80\x00\x00' 608LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF)) 609BE_FLOAT_NAN = b'\x7f\xc0\x00\x00' 610LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN)) 611 612# on non-IEEE platforms, attempting to unpack a bit pattern 613# representing an infinity or a NaN should raise an exception. 614 615@requires_setformat 616class UnknownFormatTestCase(unittest.TestCase): 617 def setUp(self): 618 self.save_formats = {'double':float.__getformat__('double'), 619 'float':float.__getformat__('float')} 620 float.__setformat__('double', 'unknown') 621 float.__setformat__('float', 'unknown') 622 623 def tearDown(self): 624 float.__setformat__('double', self.save_formats['double']) 625 float.__setformat__('float', self.save_formats['float']) 626 627 def test_double_specials_dont_unpack(self): 628 for fmt, data in [('>d', BE_DOUBLE_INF), 629 ('>d', BE_DOUBLE_NAN), 630 ('<d', LE_DOUBLE_INF), 631 ('<d', LE_DOUBLE_NAN)]: 632 self.assertRaises(ValueError, struct.unpack, fmt, data) 633 634 def test_float_specials_dont_unpack(self): 635 for fmt, data in [('>f', BE_FLOAT_INF), 636 ('>f', BE_FLOAT_NAN), 637 ('<f', LE_FLOAT_INF), 638 ('<f', LE_FLOAT_NAN)]: 639 self.assertRaises(ValueError, struct.unpack, fmt, data) 640 641 642# on an IEEE platform, all we guarantee is that bit patterns 643# representing infinities or NaNs do not raise an exception; all else 644# is accident (today). 645# let's also try to guarantee that -0.0 and 0.0 don't get confused. 646 647class IEEEFormatTestCase(unittest.TestCase): 648 649 @support.requires_IEEE_754 650 def test_double_specials_do_unpack(self): 651 for fmt, data in [('>d', BE_DOUBLE_INF), 652 ('>d', BE_DOUBLE_NAN), 653 ('<d', LE_DOUBLE_INF), 654 ('<d', LE_DOUBLE_NAN)]: 655 struct.unpack(fmt, data) 656 657 @support.requires_IEEE_754 658 def test_float_specials_do_unpack(self): 659 for fmt, data in [('>f', BE_FLOAT_INF), 660 ('>f', BE_FLOAT_NAN), 661 ('<f', LE_FLOAT_INF), 662 ('<f', LE_FLOAT_NAN)]: 663 struct.unpack(fmt, data) 664 665 # TODO(T85846583): [Pyro 3.8] PEP-384 _testcapi 666 @cpython_only 667 @support.requires_IEEE_754 668 def test_serialized_float_rounding(self): 669 from _testcapi import FLT_MAX 670 self.assertEqual(struct.pack("<f", 3.40282356e38), struct.pack("<f", FLT_MAX)) 671 self.assertEqual(struct.pack("<f", -3.40282356e38), struct.pack("<f", -FLT_MAX)) 672 673class FormatTestCase(unittest.TestCase): 674 675 def test_format(self): 676 # these should be rewritten to use both format(x, spec) and 677 # x.__format__(spec) 678 679 self.assertEqual(format(0.0, 'f'), '0.000000') 680 681 # the default is 'g', except for empty format spec 682 self.assertEqual(format(0.0, ''), '0.0') 683 self.assertEqual(format(0.01, ''), '0.01') 684 self.assertEqual(format(0.01, 'g'), '0.01') 685 686 # empty presentation type should format in the same way as str 687 # (issue 5920) 688 x = 100/7. 689 self.assertEqual(format(x, ''), str(x)) 690 self.assertEqual(format(x, '-'), str(x)) 691 self.assertEqual(format(x, '>'), str(x)) 692 self.assertEqual(format(x, '2'), str(x)) 693 694 self.assertEqual(format(1.0, 'f'), '1.000000') 695 696 self.assertEqual(format(-1.0, 'f'), '-1.000000') 697 698 self.assertEqual(format( 1.0, ' f'), ' 1.000000') 699 self.assertEqual(format(-1.0, ' f'), '-1.000000') 700 self.assertEqual(format( 1.0, '+f'), '+1.000000') 701 self.assertEqual(format(-1.0, '+f'), '-1.000000') 702 703 # % formatting 704 self.assertEqual(format(-1.0, '%'), '-100.000000%') 705 706 # conversion to string should fail 707 self.assertRaises(ValueError, format, 3.0, "s") 708 709 # other format specifiers shouldn't work on floats, 710 # in particular int specifiers 711 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] + 712 [chr(x) for x in range(ord('A'), ord('Z')+1)]): 713 if not format_spec in 'eEfFgGn%': 714 self.assertRaises(ValueError, format, 0.0, format_spec) 715 self.assertRaises(ValueError, format, 1.0, format_spec) 716 self.assertRaises(ValueError, format, -1.0, format_spec) 717 self.assertRaises(ValueError, format, 1e100, format_spec) 718 self.assertRaises(ValueError, format, -1e100, format_spec) 719 self.assertRaises(ValueError, format, 1e-100, format_spec) 720 self.assertRaises(ValueError, format, -1e-100, format_spec) 721 722 # issue 3382 723 self.assertEqual(format(NAN, 'f'), 'nan') 724 self.assertEqual(format(NAN, 'F'), 'NAN') 725 self.assertEqual(format(INF, 'f'), 'inf') 726 self.assertEqual(format(INF, 'F'), 'INF') 727 728 @support.requires_IEEE_754 729 def test_format_testfile(self): 730 with open(format_testfile) as testfile: 731 for line in testfile: 732 if line.startswith('--'): 733 continue 734 line = line.strip() 735 if not line: 736 continue 737 738 lhs, rhs = map(str.strip, line.split('->')) 739 fmt, arg = lhs.split() 740 self.assertEqual(fmt % float(arg), rhs) 741 self.assertEqual(fmt % -float(arg), '-' + rhs) 742 743 def test_issue5864(self): 744 self.assertEqual(format(123.456, '.4'), '123.5') 745 self.assertEqual(format(1234.56, '.4'), '1.235e+03') 746 self.assertEqual(format(12345.6, '.4'), '1.235e+04') 747 748 def test_issue35560(self): 749 self.assertEqual(format(123.0, '00'), '123.0') 750 self.assertEqual(format(123.34, '00f'), '123.340000') 751 self.assertEqual(format(123.34, '00e'), '1.233400e+02') 752 self.assertEqual(format(123.34, '00g'), '123.34') 753 self.assertEqual(format(123.34, '00.10f'), '123.3400000000') 754 self.assertEqual(format(123.34, '00.10e'), '1.2334000000e+02') 755 self.assertEqual(format(123.34, '00.10g'), '123.34') 756 self.assertEqual(format(123.34, '01f'), '123.340000') 757 758 self.assertEqual(format(-123.0, '00'), '-123.0') 759 self.assertEqual(format(-123.34, '00f'), '-123.340000') 760 self.assertEqual(format(-123.34, '00e'), '-1.233400e+02') 761 self.assertEqual(format(-123.34, '00g'), '-123.34') 762 self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000') 763 self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000') 764 self.assertEqual(format(-123.34, '00.10e'), '-1.2334000000e+02') 765 self.assertEqual(format(-123.34, '00.10g'), '-123.34') 766 767class ReprTestCase(unittest.TestCase): 768 # TODO(T89787302) 769 @cpython_only 770 def test_repr(self): 771 with open(os.path.join(os.path.split(__file__)[0], 772 'floating_points.txt')) as floats_file: 773 for line in floats_file: 774 line = line.strip() 775 if not line or line.startswith('#'): 776 continue 777 v = eval(line) 778 self.assertEqual(v, eval(repr(v))) 779 780 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', 781 "applies only when using short float repr style") 782 def test_short_repr(self): 783 # test short float repr introduced in Python 3.1. One aspect 784 # of this repr is that we get some degree of str -> float -> 785 # str roundtripping. In particular, for any numeric string 786 # containing 15 or fewer significant digits, those exact same 787 # digits (modulo trailing zeros) should appear in the output. 788 # No more repr(0.03) -> "0.029999999999999999"! 789 790 test_strings = [ 791 # output always includes *either* a decimal point and at 792 # least one digit after that point, or an exponent. 793 '0.0', 794 '1.0', 795 '0.01', 796 '0.02', 797 '0.03', 798 '0.04', 799 '0.05', 800 '1.23456789', 801 '10.0', 802 '100.0', 803 # values >= 1e16 get an exponent... 804 '1000000000000000.0', 805 '9999999999999990.0', 806 '1e+16', 807 '1e+17', 808 # ... and so do values < 1e-4 809 '0.001', 810 '0.001001', 811 '0.00010000000000001', 812 '0.0001', 813 '9.999999999999e-05', 814 '1e-05', 815 # values designed to provoke failure if the FPU rounding 816 # precision isn't set correctly 817 '8.72293771110361e+25', 818 '7.47005307342313e+26', 819 '2.86438000439698e+28', 820 '8.89142905246179e+28', 821 '3.08578087079232e+35', 822 ] 823 824 for s in test_strings: 825 negs = '-'+s 826 self.assertEqual(s, repr(float(s))) 827 self.assertEqual(negs, repr(float(negs))) 828 # Since Python 3.2, repr and str are identical 829 self.assertEqual(repr(float(s)), str(float(s))) 830 self.assertEqual(repr(float(negs)), str(float(negs))) 831 832@support.requires_IEEE_754 833class RoundTestCase(unittest.TestCase): 834 835 def test_inf_nan(self): 836 self.assertRaises(OverflowError, round, INF) 837 self.assertRaises(OverflowError, round, -INF) 838 self.assertRaises(ValueError, round, NAN) 839 self.assertRaises(TypeError, round, INF, 0.0) 840 self.assertRaises(TypeError, round, -INF, 1.0) 841 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer") 842 self.assertRaises(TypeError, round, -0.0, 1j) 843 844 def test_large_n(self): 845 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]: 846 self.assertEqual(round(123.456, n), 123.456) 847 self.assertEqual(round(-123.456, n), -123.456) 848 self.assertEqual(round(1e300, n), 1e300) 849 self.assertEqual(round(1e-320, n), 1e-320) 850 self.assertEqual(round(1e150, 300), 1e150) 851 self.assertEqual(round(1e300, 307), 1e300) 852 self.assertEqual(round(-3.1415, 308), -3.1415) 853 self.assertEqual(round(1e150, 309), 1e150) 854 self.assertEqual(round(1.4e-315, 315), 1e-315) 855 856 def test_small_n(self): 857 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]: 858 self.assertEqual(round(123.456, n), 0.0) 859 self.assertEqual(round(-123.456, n), -0.0) 860 self.assertEqual(round(1e300, n), 0.0) 861 self.assertEqual(round(1e-320, n), 0.0) 862 863 def test_overflow(self): 864 self.assertRaises(OverflowError, round, 1.6e308, -308) 865 self.assertRaises(OverflowError, round, -1.7e308, -308) 866 867 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', 868 "applies only when using short float repr style") 869 def test_previous_round_bugs(self): 870 # particular cases that have occurred in bug reports 871 self.assertEqual(round(562949953421312.5, 1), 872 562949953421312.5) 873 self.assertEqual(round(56294995342131.5, 3), 874 56294995342131.5) 875 # round-half-even 876 self.assertEqual(round(25.0, -1), 20.0) 877 self.assertEqual(round(35.0, -1), 40.0) 878 self.assertEqual(round(45.0, -1), 40.0) 879 self.assertEqual(round(55.0, -1), 60.0) 880 self.assertEqual(round(65.0, -1), 60.0) 881 self.assertEqual(round(75.0, -1), 80.0) 882 self.assertEqual(round(85.0, -1), 80.0) 883 self.assertEqual(round(95.0, -1), 100.0) 884 885 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', 886 "applies only when using short float repr style") 887 def test_matches_float_format(self): 888 # round should give the same results as float formatting 889 for i in range(500): 890 x = i/1000. 891 self.assertEqual(float(format(x, '.0f')), round(x, 0)) 892 self.assertEqual(float(format(x, '.1f')), round(x, 1)) 893 self.assertEqual(float(format(x, '.2f')), round(x, 2)) 894 self.assertEqual(float(format(x, '.3f')), round(x, 3)) 895 896 for i in range(5, 5000, 10): 897 x = i/1000. 898 self.assertEqual(float(format(x, '.0f')), round(x, 0)) 899 self.assertEqual(float(format(x, '.1f')), round(x, 1)) 900 self.assertEqual(float(format(x, '.2f')), round(x, 2)) 901 self.assertEqual(float(format(x, '.3f')), round(x, 3)) 902 903 for i in range(500): 904 x = random.random() 905 self.assertEqual(float(format(x, '.0f')), round(x, 0)) 906 self.assertEqual(float(format(x, '.1f')), round(x, 1)) 907 self.assertEqual(float(format(x, '.2f')), round(x, 2)) 908 self.assertEqual(float(format(x, '.3f')), round(x, 3)) 909 910 def test_format_specials(self): 911 # Test formatting of nans and infs. 912 913 def test(fmt, value, expected): 914 # Test with both % and format(). 915 self.assertEqual(fmt % value, expected, fmt) 916 fmt = fmt[1:] # strip off the % 917 self.assertEqual(format(value, fmt), expected, fmt) 918 919 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g', 920 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']: 921 pfmt = '%+' + fmt[1:] 922 sfmt = '% ' + fmt[1:] 923 test(fmt, INF, 'inf') 924 test(fmt, -INF, '-inf') 925 test(fmt, NAN, 'nan') 926 test(fmt, -NAN, 'nan') 927 # When asking for a sign, it's always provided. nans are 928 # always positive. 929 test(pfmt, INF, '+inf') 930 test(pfmt, -INF, '-inf') 931 test(pfmt, NAN, '+nan') 932 test(pfmt, -NAN, '+nan') 933 # When using ' ' for a sign code, only infs can be negative. 934 # Others have a space. 935 test(sfmt, INF, ' inf') 936 test(sfmt, -INF, '-inf') 937 test(sfmt, NAN, ' nan') 938 test(sfmt, -NAN, ' nan') 939 940 def test_None_ndigits(self): 941 for x in round(1.23), round(1.23, None), round(1.23, ndigits=None): 942 self.assertEqual(x, 1) 943 self.assertIsInstance(x, int) 944 for x in round(1.78), round(1.78, None), round(1.78, ndigits=None): 945 self.assertEqual(x, 2) 946 self.assertIsInstance(x, int) 947 948 949# Beginning with Python 2.6 float has cross platform compatible 950# ways to create and represent inf and nan 951class InfNanTest(unittest.TestCase): 952 # TODO(T89787673) 953 @cpython_only 954 def test_inf_from_str(self): 955 self.assertTrue(isinf(float("inf"))) 956 self.assertTrue(isinf(float("+inf"))) 957 self.assertTrue(isinf(float("-inf"))) 958 self.assertTrue(isinf(float("infinity"))) 959 self.assertTrue(isinf(float("+infinity"))) 960 self.assertTrue(isinf(float("-infinity"))) 961 962 self.assertEqual(repr(float("inf")), "inf") 963 self.assertEqual(repr(float("+inf")), "inf") 964 self.assertEqual(repr(float("-inf")), "-inf") 965 self.assertEqual(repr(float("infinity")), "inf") 966 self.assertEqual(repr(float("+infinity")), "inf") 967 self.assertEqual(repr(float("-infinity")), "-inf") 968 969 self.assertEqual(repr(float("INF")), "inf") 970 self.assertEqual(repr(float("+Inf")), "inf") 971 self.assertEqual(repr(float("-iNF")), "-inf") 972 self.assertEqual(repr(float("Infinity")), "inf") 973 self.assertEqual(repr(float("+iNfInItY")), "inf") 974 self.assertEqual(repr(float("-INFINITY")), "-inf") 975 976 self.assertEqual(str(float("inf")), "inf") 977 self.assertEqual(str(float("+inf")), "inf") 978 self.assertEqual(str(float("-inf")), "-inf") 979 self.assertEqual(str(float("infinity")), "inf") 980 self.assertEqual(str(float("+infinity")), "inf") 981 self.assertEqual(str(float("-infinity")), "-inf") 982 983 self.assertRaises(ValueError, float, "info") 984 self.assertRaises(ValueError, float, "+info") 985 self.assertRaises(ValueError, float, "-info") 986 self.assertRaises(ValueError, float, "in") 987 self.assertRaises(ValueError, float, "+in") 988 self.assertRaises(ValueError, float, "-in") 989 self.assertRaises(ValueError, float, "infinit") 990 self.assertRaises(ValueError, float, "+Infin") 991 self.assertRaises(ValueError, float, "-INFI") 992 self.assertRaises(ValueError, float, "infinitys") 993 994 self.assertRaises(ValueError, float, "++Inf") 995 self.assertRaises(ValueError, float, "-+inf") 996 self.assertRaises(ValueError, float, "+-infinity") 997 self.assertRaises(ValueError, float, "--Infinity") 998 999 def test_inf_as_str(self): 1000 self.assertEqual(repr(1e300 * 1e300), "inf") 1001 self.assertEqual(repr(-1e300 * 1e300), "-inf") 1002 1003 self.assertEqual(str(1e300 * 1e300), "inf") 1004 self.assertEqual(str(-1e300 * 1e300), "-inf") 1005 1006 def test_nan_from_str(self): 1007 self.assertTrue(isnan(float("nan"))) 1008 self.assertTrue(isnan(float("+nan"))) 1009 self.assertTrue(isnan(float("-nan"))) 1010 1011 self.assertEqual(repr(float("nan")), "nan") 1012 self.assertEqual(repr(float("+nan")), "nan") 1013 self.assertEqual(repr(float("-nan")), "nan") 1014 1015 self.assertEqual(repr(float("NAN")), "nan") 1016 self.assertEqual(repr(float("+NAn")), "nan") 1017 self.assertEqual(repr(float("-NaN")), "nan") 1018 1019 self.assertEqual(str(float("nan")), "nan") 1020 self.assertEqual(str(float("+nan")), "nan") 1021 self.assertEqual(str(float("-nan")), "nan") 1022 1023 self.assertRaises(ValueError, float, "nana") 1024 self.assertRaises(ValueError, float, "+nana") 1025 self.assertRaises(ValueError, float, "-nana") 1026 self.assertRaises(ValueError, float, "na") 1027 self.assertRaises(ValueError, float, "+na") 1028 self.assertRaises(ValueError, float, "-na") 1029 1030 self.assertRaises(ValueError, float, "++nan") 1031 self.assertRaises(ValueError, float, "-+NAN") 1032 self.assertRaises(ValueError, float, "+-NaN") 1033 self.assertRaises(ValueError, float, "--nAn") 1034 1035 def test_nan_as_str(self): 1036 self.assertEqual(repr(1e300 * 1e300 * 0), "nan") 1037 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan") 1038 1039 self.assertEqual(str(1e300 * 1e300 * 0), "nan") 1040 self.assertEqual(str(-1e300 * 1e300 * 0), "nan") 1041 1042 def test_inf_signs(self): 1043 self.assertEqual(copysign(1.0, float('inf')), 1.0) 1044 self.assertEqual(copysign(1.0, float('-inf')), -1.0) 1045 1046 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', 1047 "applies only when using short float repr style") 1048 def test_nan_signs(self): 1049 # When using the dtoa.c code, the sign of float('nan') should 1050 # be predictable. 1051 self.assertEqual(copysign(1.0, float('nan')), 1.0) 1052 self.assertEqual(copysign(1.0, float('-nan')), -1.0) 1053 1054 1055fromHex = float.fromhex 1056toHex = float.hex 1057class HexFloatTestCase(unittest.TestCase): 1058 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal 1059 MIN = fromHex('0x1p-1022') # min normal 1060 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal 1061 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up 1062 1063 def identical(self, x, y): 1064 # check that floats x and y are identical, or that both 1065 # are NaNs 1066 if isnan(x) or isnan(y): 1067 if isnan(x) == isnan(y): 1068 return 1069 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)): 1070 return 1071 self.fail('%r not identical to %r' % (x, y)) 1072 1073 def test_ends(self): 1074 self.identical(self.MIN, ldexp(1.0, -1022)) 1075 self.identical(self.TINY, ldexp(1.0, -1074)) 1076 self.identical(self.EPS, ldexp(1.0, -52)) 1077 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970))) 1078 1079 def test_invalid_inputs(self): 1080 invalid_inputs = [ 1081 'infi', # misspelt infinities and nans 1082 '-Infinit', 1083 '++inf', 1084 '-+Inf', 1085 '--nan', 1086 '+-NaN', 1087 'snan', 1088 'NaNs', 1089 'nna', 1090 'an', 1091 'nf', 1092 'nfinity', 1093 'inity', 1094 'iinity', 1095 '0xnan', 1096 '', 1097 ' ', 1098 'x1.0p0', 1099 '0xX1.0p0', 1100 '+ 0x1.0p0', # internal whitespace 1101 '- 0x1.0p0', 1102 '0 x1.0p0', 1103 '0x 1.0p0', 1104 '0x1 2.0p0', 1105 '+0x1 .0p0', 1106 '0x1. 0p0', 1107 '-0x1.0 1p0', 1108 '-0x1.0 p0', 1109 '+0x1.0p +0', 1110 '0x1.0p -0', 1111 '0x1.0p 0', 1112 '+0x1.0p+ 0', 1113 '-0x1.0p- 0', 1114 '++0x1.0p-0', # double signs 1115 '--0x1.0p0', 1116 '+-0x1.0p+0', 1117 '-+0x1.0p0', 1118 '0x1.0p++0', 1119 '+0x1.0p+-0', 1120 '-0x1.0p-+0', 1121 '0x1.0p--0', 1122 '0x1.0.p0', 1123 '0x.p0', # no hex digits before or after point 1124 '0x1,p0', # wrong decimal point character 1125 '0x1pa', 1126 '0x1p\uff10', # fullwidth Unicode digits 1127 '\uff10x1p0', 1128 '0x\uff11p0', 1129 '0x1.\uff10p0', 1130 '0x1p0 \n 0x2p0', 1131 '0x1p0\0 0x1p0', # embedded null byte is not end of string 1132 ] 1133 for x in invalid_inputs: 1134 try: 1135 result = fromHex(x) 1136 except ValueError: 1137 pass 1138 else: 1139 self.fail('Expected float.fromhex(%r) to raise ValueError; ' 1140 'got %r instead' % (x, result)) 1141 1142 1143 def test_whitespace(self): 1144 value_pairs = [ 1145 ('inf', INF), 1146 ('-Infinity', -INF), 1147 ('nan', NAN), 1148 ('1.0', 1.0), 1149 ('-0x.2', -0.125), 1150 ('-0.0', -0.0) 1151 ] 1152 whitespace = [ 1153 '', 1154 ' ', 1155 '\t', 1156 '\n', 1157 '\n \t', 1158 '\f', 1159 '\v', 1160 '\r' 1161 ] 1162 for inp, expected in value_pairs: 1163 for lead in whitespace: 1164 for trail in whitespace: 1165 got = fromHex(lead + inp + trail) 1166 self.identical(got, expected) 1167 1168 1169 def test_from_hex(self): 1170 MIN = self.MIN; 1171 MAX = self.MAX; 1172 TINY = self.TINY; 1173 EPS = self.EPS; 1174 1175 # two spellings of infinity, with optional signs; case-insensitive 1176 self.identical(fromHex('inf'), INF) 1177 self.identical(fromHex('+Inf'), INF) 1178 self.identical(fromHex('-INF'), -INF) 1179 self.identical(fromHex('iNf'), INF) 1180 self.identical(fromHex('Infinity'), INF) 1181 self.identical(fromHex('+INFINITY'), INF) 1182 self.identical(fromHex('-infinity'), -INF) 1183 self.identical(fromHex('-iNFiNitY'), -INF) 1184 1185 # nans with optional sign; case insensitive 1186 self.identical(fromHex('nan'), NAN) 1187 self.identical(fromHex('+NaN'), NAN) 1188 self.identical(fromHex('-NaN'), NAN) 1189 self.identical(fromHex('-nAN'), NAN) 1190 1191 # variations in input format 1192 self.identical(fromHex('1'), 1.0) 1193 self.identical(fromHex('+1'), 1.0) 1194 self.identical(fromHex('1.'), 1.0) 1195 self.identical(fromHex('1.0'), 1.0) 1196 self.identical(fromHex('1.0p0'), 1.0) 1197 self.identical(fromHex('01'), 1.0) 1198 self.identical(fromHex('01.'), 1.0) 1199 self.identical(fromHex('0x1'), 1.0) 1200 self.identical(fromHex('0x1.'), 1.0) 1201 self.identical(fromHex('0x1.0'), 1.0) 1202 self.identical(fromHex('+0x1.0'), 1.0) 1203 self.identical(fromHex('0x1p0'), 1.0) 1204 self.identical(fromHex('0X1p0'), 1.0) 1205 self.identical(fromHex('0X1P0'), 1.0) 1206 self.identical(fromHex('0x1P0'), 1.0) 1207 self.identical(fromHex('0x1.p0'), 1.0) 1208 self.identical(fromHex('0x1.0p0'), 1.0) 1209 self.identical(fromHex('0x.1p4'), 1.0) 1210 self.identical(fromHex('0x.1p04'), 1.0) 1211 self.identical(fromHex('0x.1p004'), 1.0) 1212 self.identical(fromHex('0x1p+0'), 1.0) 1213 self.identical(fromHex('0x1P-0'), 1.0) 1214 self.identical(fromHex('+0x1p0'), 1.0) 1215 self.identical(fromHex('0x01p0'), 1.0) 1216 self.identical(fromHex('0x1p00'), 1.0) 1217 self.identical(fromHex(' 0x1p0 '), 1.0) 1218 self.identical(fromHex('\n 0x1p0'), 1.0) 1219 self.identical(fromHex('0x1p0 \t'), 1.0) 1220 self.identical(fromHex('0xap0'), 10.0) 1221 self.identical(fromHex('0xAp0'), 10.0) 1222 self.identical(fromHex('0xaP0'), 10.0) 1223 self.identical(fromHex('0xAP0'), 10.0) 1224 self.identical(fromHex('0xbep0'), 190.0) 1225 self.identical(fromHex('0xBep0'), 190.0) 1226 self.identical(fromHex('0xbEp0'), 190.0) 1227 self.identical(fromHex('0XBE0P-4'), 190.0) 1228 self.identical(fromHex('0xBEp0'), 190.0) 1229 self.identical(fromHex('0xB.Ep4'), 190.0) 1230 self.identical(fromHex('0x.BEp8'), 190.0) 1231 self.identical(fromHex('0x.0BEp12'), 190.0) 1232 1233 # moving the point around 1234 pi = fromHex('0x1.921fb54442d18p1') 1235 self.identical(fromHex('0x.006487ed5110b46p11'), pi) 1236 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi) 1237 self.identical(fromHex('0x.01921fb54442d18p9'), pi) 1238 self.identical(fromHex('0x.03243f6a8885a3p8'), pi) 1239 self.identical(fromHex('0x.06487ed5110b46p7'), pi) 1240 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi) 1241 self.identical(fromHex('0x.1921fb54442d18p5'), pi) 1242 self.identical(fromHex('0x.3243f6a8885a3p4'), pi) 1243 self.identical(fromHex('0x.6487ed5110b46p3'), pi) 1244 self.identical(fromHex('0x.c90fdaa22168cp2'), pi) 1245 self.identical(fromHex('0x1.921fb54442d18p1'), pi) 1246 self.identical(fromHex('0x3.243f6a8885a3p0'), pi) 1247 self.identical(fromHex('0x6.487ed5110b46p-1'), pi) 1248 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi) 1249 self.identical(fromHex('0x19.21fb54442d18p-3'), pi) 1250 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi) 1251 self.identical(fromHex('0x64.87ed5110b46p-5'), pi) 1252 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi) 1253 self.identical(fromHex('0x192.1fb54442d18p-7'), pi) 1254 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi) 1255 self.identical(fromHex('0x648.7ed5110b46p-9'), pi) 1256 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi) 1257 self.identical(fromHex('0x1921.fb54442d18p-11'), pi) 1258 # ... 1259 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi) 1260 self.identical(fromHex('0x3243f6a8885a3p-48'), pi) 1261 self.identical(fromHex('0x6487ed5110b46p-49'), pi) 1262 self.identical(fromHex('0xc90fdaa22168cp-50'), pi) 1263 self.identical(fromHex('0x1921fb54442d18p-51'), pi) 1264 self.identical(fromHex('0x3243f6a8885a30p-52'), pi) 1265 self.identical(fromHex('0x6487ed5110b460p-53'), pi) 1266 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi) 1267 self.identical(fromHex('0x1921fb54442d180p-55'), pi) 1268 1269 1270 # results that should overflow... 1271 self.assertRaises(OverflowError, fromHex, '-0x1p1024') 1272 self.assertRaises(OverflowError, fromHex, '0x1p+1025') 1273 self.assertRaises(OverflowError, fromHex, '+0X1p1030') 1274 self.assertRaises(OverflowError, fromHex, '-0x1p+1100') 1275 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789') 1276 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025') 1277 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025') 1278 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026') 1279 self.assertRaises(OverflowError, fromHex, '0X2p+1023') 1280 self.assertRaises(OverflowError, fromHex, '0x2.p1023') 1281 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023') 1282 self.assertRaises(OverflowError, fromHex, '+0X4p+1022') 1283 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023') 1284 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023') 1285 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023') 1286 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022') 1287 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970') 1288 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960') 1289 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960') 1290 1291 # ...and those that round to +-max float 1292 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX) 1293 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX) 1294 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX) 1295 1296 # zeros 1297 self.identical(fromHex('0x0p0'), 0.0) 1298 self.identical(fromHex('0x0p1000'), 0.0) 1299 self.identical(fromHex('-0x0p1023'), -0.0) 1300 self.identical(fromHex('0X0p1024'), 0.0) 1301 self.identical(fromHex('-0x0p1025'), -0.0) 1302 self.identical(fromHex('0X0p2000'), 0.0) 1303 self.identical(fromHex('0x0p123456789123456789'), 0.0) 1304 self.identical(fromHex('-0X0p-0'), -0.0) 1305 self.identical(fromHex('-0X0p-1000'), -0.0) 1306 self.identical(fromHex('0x0p-1023'), 0.0) 1307 self.identical(fromHex('-0X0p-1024'), -0.0) 1308 self.identical(fromHex('-0x0p-1025'), -0.0) 1309 self.identical(fromHex('-0x0p-1072'), -0.0) 1310 self.identical(fromHex('0X0p-1073'), 0.0) 1311 self.identical(fromHex('-0x0p-1074'), -0.0) 1312 self.identical(fromHex('0x0p-1075'), 0.0) 1313 self.identical(fromHex('0X0p-1076'), 0.0) 1314 self.identical(fromHex('-0X0p-2000'), -0.0) 1315 self.identical(fromHex('-0x0p-123456789123456789'), -0.0) 1316 1317 # values that should underflow to 0 1318 self.identical(fromHex('0X1p-1075'), 0.0) 1319 self.identical(fromHex('-0X1p-1075'), -0.0) 1320 self.identical(fromHex('-0x1p-123456789123456789'), -0.0) 1321 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY) 1322 self.identical(fromHex('-0x1.1p-1075'), -TINY) 1323 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY) 1324 1325 # check round-half-even is working correctly near 0 ... 1326 self.identical(fromHex('0x1p-1076'), 0.0) 1327 self.identical(fromHex('0X2p-1076'), 0.0) 1328 self.identical(fromHex('0X3p-1076'), TINY) 1329 self.identical(fromHex('0x4p-1076'), TINY) 1330 self.identical(fromHex('0X5p-1076'), TINY) 1331 self.identical(fromHex('0X6p-1076'), 2*TINY) 1332 self.identical(fromHex('0x7p-1076'), 2*TINY) 1333 self.identical(fromHex('0X8p-1076'), 2*TINY) 1334 self.identical(fromHex('0X9p-1076'), 2*TINY) 1335 self.identical(fromHex('0xap-1076'), 2*TINY) 1336 self.identical(fromHex('0Xbp-1076'), 3*TINY) 1337 self.identical(fromHex('0xcp-1076'), 3*TINY) 1338 self.identical(fromHex('0Xdp-1076'), 3*TINY) 1339 self.identical(fromHex('0Xep-1076'), 4*TINY) 1340 self.identical(fromHex('0xfp-1076'), 4*TINY) 1341 self.identical(fromHex('0x10p-1076'), 4*TINY) 1342 self.identical(fromHex('-0x1p-1076'), -0.0) 1343 self.identical(fromHex('-0X2p-1076'), -0.0) 1344 self.identical(fromHex('-0x3p-1076'), -TINY) 1345 self.identical(fromHex('-0X4p-1076'), -TINY) 1346 self.identical(fromHex('-0x5p-1076'), -TINY) 1347 self.identical(fromHex('-0x6p-1076'), -2*TINY) 1348 self.identical(fromHex('-0X7p-1076'), -2*TINY) 1349 self.identical(fromHex('-0X8p-1076'), -2*TINY) 1350 self.identical(fromHex('-0X9p-1076'), -2*TINY) 1351 self.identical(fromHex('-0Xap-1076'), -2*TINY) 1352 self.identical(fromHex('-0xbp-1076'), -3*TINY) 1353 self.identical(fromHex('-0xcp-1076'), -3*TINY) 1354 self.identical(fromHex('-0Xdp-1076'), -3*TINY) 1355 self.identical(fromHex('-0xep-1076'), -4*TINY) 1356 self.identical(fromHex('-0Xfp-1076'), -4*TINY) 1357 self.identical(fromHex('-0X10p-1076'), -4*TINY) 1358 1359 # ... and near MIN ... 1360 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY) 1361 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY) 1362 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY) 1363 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY) 1364 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY) 1365 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY) 1366 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY) 1367 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY) 1368 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY) 1369 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY) 1370 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY) 1371 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY) 1372 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY) 1373 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY) 1374 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY) 1375 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY) 1376 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY) 1377 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN) 1378 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN) 1379 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN) 1380 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN) 1381 self.identical(fromHex('0x1.00000000000000p-1022'), MIN) 1382 self.identical(fromHex('0x1.00000000000002p-1022'), MIN) 1383 self.identical(fromHex('0x1.00000000000004p-1022'), MIN) 1384 self.identical(fromHex('0x1.00000000000006p-1022'), MIN) 1385 self.identical(fromHex('0x1.00000000000008p-1022'), MIN) 1386 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY) 1387 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY) 1388 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY) 1389 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY) 1390 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY) 1391 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY) 1392 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY) 1393 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY) 1394 1395 # ... and near 1.0. 1396 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS) 1397 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS) 1398 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS) 1399 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS) 1400 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS) 1401 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2) 1402 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2) 1403 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2) 1404 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2) 1405 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2) 1406 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2) 1407 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2) 1408 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0) 1409 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0) 1410 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0) 1411 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0) 1412 self.identical(fromHex('0X1.00000000000000p0'), 1.0) 1413 self.identical(fromHex('0X1.00000000000001p0'), 1.0) 1414 self.identical(fromHex('0x1.00000000000002p0'), 1.0) 1415 self.identical(fromHex('0X1.00000000000003p0'), 1.0) 1416 self.identical(fromHex('0x1.00000000000004p0'), 1.0) 1417 self.identical(fromHex('0X1.00000000000005p0'), 1.0) 1418 self.identical(fromHex('0X1.00000000000006p0'), 1.0) 1419 self.identical(fromHex('0X1.00000000000007p0'), 1.0) 1420 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'), 1421 1.0) 1422 self.identical(fromHex('0x1.00000000000008p0'), 1.0) 1423 self.identical(fromHex('0x1.00000000000008000000000000000001p0'), 1424 1+EPS) 1425 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS) 1426 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS) 1427 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS) 1428 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS) 1429 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS) 1430 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS) 1431 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS) 1432 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS) 1433 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS) 1434 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS) 1435 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS) 1436 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS) 1437 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS) 1438 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS) 1439 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS) 1440 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'), 1441 1.0+EPS) 1442 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS) 1443 self.identical(fromHex('0X1.00000000000018000000000000000001p0'), 1444 1.0+2*EPS) 1445 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS) 1446 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS) 1447 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS) 1448 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS) 1449 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS) 1450 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS) 1451 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS) 1452 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS) 1453 1454 def test_roundtrip(self): 1455 def roundtrip(x): 1456 return fromHex(toHex(x)) 1457 1458 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]: 1459 self.identical(x, roundtrip(x)) 1460 self.identical(-x, roundtrip(-x)) 1461 1462 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x. 1463 import random 1464 for i in range(10000): 1465 e = random.randrange(-1200, 1200) 1466 m = random.random() 1467 s = random.choice([1.0, -1.0]) 1468 try: 1469 x = s*ldexp(m, e) 1470 except OverflowError: 1471 pass 1472 else: 1473 self.identical(x, fromHex(toHex(x))) 1474 1475 def test_subclass(self): 1476 class F(float): 1477 def __new__(cls, value): 1478 return float.__new__(cls, value + 1) 1479 1480 f = F.fromhex((1.5).hex()) 1481 self.assertIs(type(f), F) 1482 self.assertEqual(f, 2.5) 1483 1484 class F2(float): 1485 def __init__(self, value): 1486 self.foo = 'bar' 1487 1488 f = F2.fromhex((1.5).hex()) 1489 self.assertIs(type(f), F2) 1490 self.assertEqual(f, 1.5) 1491 self.assertEqual(getattr(f, 'foo', 'none'), 'bar') 1492 1493 1494if __name__ == '__main__': 1495 unittest.main()