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