blob: 564f24f0c03e9bad0d1262198b08efa8025db11f [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes284d9272007-12-10 22:28:56 +00003import os
Michael W. Hudsonba283e22005-05-27 15:23:20 +00004from test import test_support
Christian Heimes6f341092008-04-18 23:13:07 +00005import math
Mark Dickinson7103aa42008-07-15 19:08:33 +00006from math import isinf, isnan, copysign, ldexp
Christian Heimes6f341092008-04-18 23:13:07 +00007import operator
Mark Dickinsonbd15a062009-11-18 19:33:35 +00008import random
9import fractions
10import sys
Michael W. Hudsonba283e22005-05-27 15:23:20 +000011
Christian Heimes6f341092008-04-18 23:13:07 +000012INF = float("inf")
13NAN = float("nan")
Christian Heimes0a8143f2007-12-18 23:22:54 +000014
Mark Dickinson61a0d052009-04-29 21:57:15 +000015#locate file with float format test values
16test_dir = os.path.dirname(__file__) or os.curdir
17format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
18
Benjamin Peterson979395b2008-05-03 21:35:18 +000019class GeneralFloatCases(unittest.TestCase):
20
21 def test_float(self):
22 self.assertEqual(float(3.14), 3.14)
23 self.assertEqual(float(314), 314.0)
24 self.assertEqual(float(314L), 314.0)
25 self.assertEqual(float(" 3.14 "), 3.14)
26 self.assertRaises(ValueError, float, " 0x3.1 ")
27 self.assertRaises(ValueError, float, " -0x3.p-1 ")
28 self.assertRaises(ValueError, float, " +0x3.p-1 ")
29 self.assertRaises(ValueError, float, "++3.14")
30 self.assertRaises(ValueError, float, "+-3.14")
31 self.assertRaises(ValueError, float, "-+3.14")
32 self.assertRaises(ValueError, float, "--3.14")
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +000033 if test_support.have_unicode:
Benjamin Peterson979395b2008-05-03 21:35:18 +000034 self.assertEqual(float(unicode(" 3.14 ")), 3.14)
35 self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
Benjamin Peterson979395b2008-05-03 21:35:18 +000036
Mark Dickinson53e9fa42009-10-27 22:09:33 +000037 # extra long strings should no longer be a problem
38 # (in 2.6, long unicode inputs to float raised ValueError)
39 float('.' + '1'*1000)
40 float(unicode('.' + '1'*1000))
41
Benjamin Peterson979395b2008-05-03 21:35:18 +000042 @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
43 def test_float_with_comma(self):
44 # set locale to something that doesn't use '.' for the decimal point
45 # float must not accept the locale specific decimal point but
46 # it still has to accept the normal python syntac
47 import locale
48 if not locale.localeconv()['decimal_point'] == ',':
49 return
50
51 self.assertEqual(float(" 3.14 "), 3.14)
52 self.assertEqual(float("+3.14 "), 3.14)
53 self.assertEqual(float("-3.14 "), -3.14)
54 self.assertEqual(float(".14 "), .14)
55 self.assertEqual(float("3. "), 3.0)
56 self.assertEqual(float("3.e3 "), 3000.0)
57 self.assertEqual(float("3.2e3 "), 3200.0)
58 self.assertEqual(float("2.5e-1 "), 0.25)
59 self.assertEqual(float("5e-1"), 0.5)
60 self.assertRaises(ValueError, float, " 3,14 ")
61 self.assertRaises(ValueError, float, " +3,14 ")
62 self.assertRaises(ValueError, float, " -3,14 ")
63 self.assertRaises(ValueError, float, " 0x3.1 ")
64 self.assertRaises(ValueError, float, " -0x3.p-1 ")
65 self.assertRaises(ValueError, float, " +0x3.p-1 ")
66 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersona853a892008-09-06 23:19:15 +000067 self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
Benjamin Peterson979395b2008-05-03 21:35:18 +000068
69 def test_floatconversion(self):
70 # Make sure that calls to __float__() work properly
71 class Foo0:
72 def __float__(self):
73 return 42.
74
75 class Foo1(object):
76 def __float__(self):
77 return 42.
78
79 class Foo2(float):
80 def __float__(self):
81 return 42.
82
83 class Foo3(float):
84 def __new__(cls, value=0.):
85 return float.__new__(cls, 2*value)
86
87 def __float__(self):
88 return self
89
90 class Foo4(float):
91 def __float__(self):
92 return 42
93
Benjamin Peterson99d36f12009-04-15 21:26:36 +000094 # Issue 5759: __float__ not called on str subclasses (though it is on
95 # unicode subclasses).
96 class FooStr(str):
97 def __float__(self):
98 return float(str(self)) + 1
99
100 class FooUnicode(unicode):
101 def __float__(self):
102 return float(unicode(self)) + 1
103
Benjamin Peterson979395b2008-05-03 21:35:18 +0000104 self.assertAlmostEqual(float(Foo0()), 42.)
105 self.assertAlmostEqual(float(Foo1()), 42.)
106 self.assertAlmostEqual(float(Foo2()), 42.)
107 self.assertAlmostEqual(float(Foo3(21)), 42.)
108 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000109 self.assertAlmostEqual(float(FooUnicode('8')), 9.)
110 self.assertAlmostEqual(float(FooStr('8')), 9.)
Benjamin Peterson979395b2008-05-03 21:35:18 +0000111
112 def test_floatasratio(self):
113 for f, ratio in [
114 (0.875, (7, 8)),
115 (-0.875, (-7, 8)),
116 (0.0, (0, 1)),
117 (11.5, (23, 2)),
118 ]:
119 self.assertEqual(f.as_integer_ratio(), ratio)
120
121 for i in range(10000):
122 f = random.random()
123 f *= 10 ** random.randint(-100, 100)
124 n, d = f.as_integer_ratio()
125 self.assertEqual(float(n).__truediv__(d), f)
126
127 R = fractions.Fraction
128 self.assertEqual(R(0, 1),
129 R(*float(0.0).as_integer_ratio()))
130 self.assertEqual(R(5, 2),
131 R(*float(2.5).as_integer_ratio()))
132 self.assertEqual(R(1, 2),
133 R(*float(0.5).as_integer_ratio()))
134 self.assertEqual(R(4728779608739021, 2251799813685248),
135 R(*float(2.1).as_integer_ratio()))
136 self.assertEqual(R(-4728779608739021, 2251799813685248),
137 R(*float(-2.1).as_integer_ratio()))
138 self.assertEqual(R(-2100, 1),
139 R(*float(-2100.0).as_integer_ratio()))
140
141 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
142 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
143 self.assertRaises(ValueError, float('nan').as_integer_ratio)
144
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000145class FormatFunctionsTestCase(unittest.TestCase):
146
147 def setUp(self):
148 self.save_formats = {'double':float.__getformat__('double'),
149 'float':float.__getformat__('float')}
150
151 def tearDown(self):
152 float.__setformat__('double', self.save_formats['double'])
153 float.__setformat__('float', self.save_formats['float'])
154
155 def test_getformat(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000156 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000157 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000158 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000159 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
160 self.assertRaises(ValueError, float.__getformat__, 'chicken')
161 self.assertRaises(TypeError, float.__getformat__, 1)
162
163 def test_setformat(self):
164 for t in 'double', 'float':
165 float.__setformat__(t, 'unknown')
166 if self.save_formats[t] == 'IEEE, big-endian':
167 self.assertRaises(ValueError, float.__setformat__,
168 t, 'IEEE, little-endian')
169 elif self.save_formats[t] == 'IEEE, little-endian':
170 self.assertRaises(ValueError, float.__setformat__,
171 t, 'IEEE, big-endian')
172 else:
173 self.assertRaises(ValueError, float.__setformat__,
174 t, 'IEEE, big-endian')
175 self.assertRaises(ValueError, float.__setformat__,
176 t, 'IEEE, little-endian')
177 self.assertRaises(ValueError, float.__setformat__,
178 t, 'chicken')
179 self.assertRaises(ValueError, float.__setformat__,
180 'chicken', 'unknown')
181
182BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
183LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
184BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
185LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
186
187BE_FLOAT_INF = '\x7f\x80\x00\x00'
188LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
189BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
190LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
191
192# on non-IEEE platforms, attempting to unpack a bit pattern
193# representing an infinity or a NaN should raise an exception.
194
195class UnknownFormatTestCase(unittest.TestCase):
196 def setUp(self):
197 self.save_formats = {'double':float.__getformat__('double'),
198 'float':float.__getformat__('float')}
199 float.__setformat__('double', 'unknown')
200 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000201
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000202 def tearDown(self):
203 float.__setformat__('double', self.save_formats['double'])
204 float.__setformat__('float', self.save_formats['float'])
205
206 def test_double_specials_dont_unpack(self):
207 for fmt, data in [('>d', BE_DOUBLE_INF),
208 ('>d', BE_DOUBLE_NAN),
209 ('<d', LE_DOUBLE_INF),
210 ('<d', LE_DOUBLE_NAN)]:
211 self.assertRaises(ValueError, struct.unpack, fmt, data)
212
213 def test_float_specials_dont_unpack(self):
214 for fmt, data in [('>f', BE_FLOAT_INF),
215 ('>f', BE_FLOAT_NAN),
216 ('<f', LE_FLOAT_INF),
217 ('<f', LE_FLOAT_NAN)]:
218 self.assertRaises(ValueError, struct.unpack, fmt, data)
219
220
221# on an IEEE platform, all we guarantee is that bit patterns
222# representing infinities or NaNs do not raise an exception; all else
223# is accident (today).
Alex Martellid8672aa2007-08-22 21:14:17 +0000224# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000225
226class IEEEFormatTestCase(unittest.TestCase):
227 if float.__getformat__("double").startswith("IEEE"):
228 def test_double_specials_do_unpack(self):
229 for fmt, data in [('>d', BE_DOUBLE_INF),
230 ('>d', BE_DOUBLE_NAN),
231 ('<d', LE_DOUBLE_INF),
232 ('<d', LE_DOUBLE_NAN)]:
233 struct.unpack(fmt, data)
234
235 if float.__getformat__("float").startswith("IEEE"):
236 def test_float_specials_do_unpack(self):
237 for fmt, data in [('>f', BE_FLOAT_INF),
238 ('>f', BE_FLOAT_NAN),
239 ('<f', LE_FLOAT_INF),
240 ('<f', LE_FLOAT_NAN)]:
241 struct.unpack(fmt, data)
242
Alex Martellid8672aa2007-08-22 21:14:17 +0000243 if float.__getformat__("double").startswith("IEEE"):
244 def test_negative_zero(self):
245 import math
246 def pos_pos():
247 return 0.0, math.atan2(0.0, -1)
248 def pos_neg():
249 return 0.0, math.atan2(-0.0, -1)
250 def neg_pos():
251 return -0.0, math.atan2(0.0, -1)
252 def neg_neg():
253 return -0.0, math.atan2(-0.0, -1)
254 self.assertEquals(pos_pos(), neg_pos())
255 self.assertEquals(pos_neg(), neg_neg())
256
Guido van Rossum3b835492008-01-05 00:59:59 +0000257 if float.__getformat__("double").startswith("IEEE"):
258 def test_underflow_sign(self):
259 import math
260 # check that -1e-1000 gives -0.0, not 0.0
261 self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
262 self.assertEquals(math.atan2(float('-1e-1000'), -1),
263 math.atan2(-0.0, -1))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000264
Eric Smitha985a3a2009-05-05 18:26:08 +0000265 def test_format(self):
266 # these should be rewritten to use both format(x, spec) and
267 # x.__format__(spec)
268
269 self.assertEqual(format(0.0, 'f'), '0.000000')
270
271 # the default is 'g', except for empty format spec
272 self.assertEqual(format(0.0, ''), '0.0')
273 self.assertEqual(format(0.01, ''), '0.01')
274 self.assertEqual(format(0.01, 'g'), '0.01')
275
276 # empty presentation type should format in the same way as str
277 # (issue 5920)
278 x = 100/7.
279 self.assertEqual(format(x, ''), str(x))
280 self.assertEqual(format(x, '-'), str(x))
281 self.assertEqual(format(x, '>'), str(x))
282 self.assertEqual(format(x, '2'), str(x))
283
284 self.assertEqual(format(1.0, 'f'), '1.000000')
285
286 self.assertEqual(format(-1.0, 'f'), '-1.000000')
287
288 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
289 self.assertEqual(format(-1.0, ' f'), '-1.000000')
290 self.assertEqual(format( 1.0, '+f'), '+1.000000')
291 self.assertEqual(format(-1.0, '+f'), '-1.000000')
292
293 # % formatting
294 self.assertEqual(format(-1.0, '%'), '-100.000000%')
295
296 # conversion to string should fail
297 self.assertRaises(ValueError, format, 3.0, "s")
298
299 # other format specifiers shouldn't work on floats,
300 # in particular int specifiers
301 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
302 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
303 if not format_spec in 'eEfFgGn%':
304 self.assertRaises(ValueError, format, 0.0, format_spec)
305 self.assertRaises(ValueError, format, 1.0, format_spec)
306 self.assertRaises(ValueError, format, -1.0, format_spec)
307 self.assertRaises(ValueError, format, 1e100, format_spec)
308 self.assertRaises(ValueError, format, -1e100, format_spec)
309 self.assertRaises(ValueError, format, 1e-100, format_spec)
310 self.assertRaises(ValueError, format, -1e-100, format_spec)
311
Eric Smithc4ab8332009-11-29 17:40:57 +0000312 # issue 3382: 'f' and 'F' with inf's and nan's
313 self.assertEqual('{0:f}'.format(INF), 'inf')
314 self.assertEqual('{0:F}'.format(INF), 'INF')
315 self.assertEqual('{0:f}'.format(-INF), '-inf')
316 self.assertEqual('{0:F}'.format(-INF), '-INF')
317 self.assertEqual('{0:f}'.format(NAN), 'nan')
318 self.assertEqual('{0:F}'.format(NAN), 'NAN')
319
Mark Dickinson61a0d052009-04-29 21:57:15 +0000320 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
321 "test requires IEEE 754 doubles")
322 def test_format_testfile(self):
323 for line in open(format_testfile):
324 if line.startswith('--'):
325 continue
326 line = line.strip()
327 if not line:
328 continue
329
330 lhs, rhs = map(str.strip, line.split('->'))
331 fmt, arg = lhs.split()
Eric Smithc4ab8332009-11-29 17:40:57 +0000332 arg = float(arg)
333 self.assertEqual(fmt % arg, rhs)
334 if not math.isnan(arg) and copysign(1.0, arg) > 0.0:
335 self.assertEqual(fmt % -arg, '-' + rhs)
Mark Dickinson61a0d052009-04-29 21:57:15 +0000336
Mark Dickinson92fcc9c2009-04-29 20:41:00 +0000337 def test_issue5864(self):
338 self.assertEquals(format(123.456, '.4'), '123.5')
339 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
340 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
341
Christian Heimes284d9272007-12-10 22:28:56 +0000342class ReprTestCase(unittest.TestCase):
343 def test_repr(self):
344 floats_file = open(os.path.join(os.path.split(__file__)[0],
345 'floating_points.txt'))
346 for line in floats_file:
347 line = line.strip()
348 if not line or line.startswith('#'):
349 continue
350 v = eval(line)
351 self.assertEqual(v, eval(repr(v)))
352 floats_file.close()
353
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000354@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
355 "test requires IEEE 754 doubles")
356class RoundTestCase(unittest.TestCase):
357 def test_second_argument_type(self):
358 # any type with an __index__ method should be permitted as
359 # a second argument
360 self.assertAlmostEqual(round(12.34, True), 12.3)
361
362 class MyIndex(object):
363 def __index__(self): return 4
364 self.assertAlmostEqual(round(-0.123456, MyIndex()), -0.1235)
365 # but floats should be illegal
366 self.assertRaises(TypeError, round, 3.14159, 2.0)
367
368 def test_inf_nan(self):
369 # rounding an infinity or nan returns the same number;
370 # (in py3k, rounding an infinity or nan raises an error,
371 # since the result can't be represented as a long).
372 self.assertEqual(round(INF), INF)
373 self.assertEqual(round(-INF), -INF)
374 self.assertTrue(math.isnan(round(NAN)))
375 for n in range(-5, 5):
376 self.assertEqual(round(INF, n), INF)
377 self.assertEqual(round(-INF, n), -INF)
378 self.assertTrue(math.isnan(round(NAN, n)))
379
Mark Dickinsonbce78372009-11-24 10:54:58 +0000380 self.assertRaises(TypeError, round, INF, 0.0)
381 self.assertRaises(TypeError, round, -INF, 1.0)
382 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
383 self.assertRaises(TypeError, round, -0.0, 1j)
384
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000385 def test_large_n(self):
386 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
387 self.assertEqual(round(123.456, n), 123.456)
388 self.assertEqual(round(-123.456, n), -123.456)
389 self.assertEqual(round(1e300, n), 1e300)
390 self.assertEqual(round(1e-320, n), 1e-320)
391 self.assertEqual(round(1e150, 300), 1e150)
392 self.assertEqual(round(1e300, 307), 1e300)
393 self.assertEqual(round(-3.1415, 308), -3.1415)
394 self.assertEqual(round(1e150, 309), 1e150)
395 self.assertEqual(round(1.4e-315, 315), 1e-315)
396
397 def test_small_n(self):
398 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
399 self.assertEqual(round(123.456, n), 0.0)
400 self.assertEqual(round(-123.456, n), -0.0)
401 self.assertEqual(round(1e300, n), 0.0)
402 self.assertEqual(round(1e-320, n), 0.0)
403
404 def test_overflow(self):
405 self.assertRaises(OverflowError, round, 1.6e308, -308)
406 self.assertRaises(OverflowError, round, -1.7e308, -308)
407
408 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
409 "test applies only when using short float repr style")
410 def test_previous_round_bugs(self):
411 # particular cases that have occurred in bug reports
412 self.assertEqual(round(562949953421312.5, 1),
413 562949953421312.5)
414 self.assertEqual(round(56294995342131.5, 3),
415 56294995342131.5)
416
417 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
418 "test applies only when using short float repr style")
419 def test_halfway_cases(self):
420 # Halfway cases need special attention, since the current
421 # implementation has to deal with them specially. Note that
422 # 2.x rounds halfway values up (i.e., away from zero) while
423 # 3.x does round-half-to-even.
424 self.assertAlmostEqual(round(0.125, 2), 0.13)
425 self.assertAlmostEqual(round(0.375, 2), 0.38)
426 self.assertAlmostEqual(round(0.625, 2), 0.63)
427 self.assertAlmostEqual(round(0.875, 2), 0.88)
428 self.assertAlmostEqual(round(-0.125, 2), -0.13)
429 self.assertAlmostEqual(round(-0.375, 2), -0.38)
430 self.assertAlmostEqual(round(-0.625, 2), -0.63)
431 self.assertAlmostEqual(round(-0.875, 2), -0.88)
432
433 self.assertAlmostEqual(round(0.25, 1), 0.3)
434 self.assertAlmostEqual(round(0.75, 1), 0.8)
435 self.assertAlmostEqual(round(-0.25, 1), -0.3)
436 self.assertAlmostEqual(round(-0.75, 1), -0.8)
437
438 self.assertEqual(round(-6.5, 0), -7.0)
439 self.assertEqual(round(-5.5, 0), -6.0)
440 self.assertEqual(round(-1.5, 0), -2.0)
441 self.assertEqual(round(-0.5, 0), -1.0)
442 self.assertEqual(round(0.5, 0), 1.0)
443 self.assertEqual(round(1.5, 0), 2.0)
444 self.assertEqual(round(2.5, 0), 3.0)
445 self.assertEqual(round(3.5, 0), 4.0)
446 self.assertEqual(round(4.5, 0), 5.0)
447 self.assertEqual(round(5.5, 0), 6.0)
448 self.assertEqual(round(6.5, 0), 7.0)
449
450 # same but without an explicit second argument; in 3.x these
451 # will give integers
452 self.assertEqual(round(-6.5), -7.0)
453 self.assertEqual(round(-5.5), -6.0)
454 self.assertEqual(round(-1.5), -2.0)
455 self.assertEqual(round(-0.5), -1.0)
456 self.assertEqual(round(0.5), 1.0)
457 self.assertEqual(round(1.5), 2.0)
458 self.assertEqual(round(2.5), 3.0)
459 self.assertEqual(round(3.5), 4.0)
460 self.assertEqual(round(4.5), 5.0)
461 self.assertEqual(round(5.5), 6.0)
462 self.assertEqual(round(6.5), 7.0)
463
464 self.assertEqual(round(-25.0, -1), -30.0)
465 self.assertEqual(round(-15.0, -1), -20.0)
466 self.assertEqual(round(-5.0, -1), -10.0)
467 self.assertEqual(round(5.0, -1), 10.0)
468 self.assertEqual(round(15.0, -1), 20.0)
469 self.assertEqual(round(25.0, -1), 30.0)
470 self.assertEqual(round(35.0, -1), 40.0)
471 self.assertEqual(round(45.0, -1), 50.0)
472 self.assertEqual(round(55.0, -1), 60.0)
473 self.assertEqual(round(65.0, -1), 70.0)
474 self.assertEqual(round(75.0, -1), 80.0)
475 self.assertEqual(round(85.0, -1), 90.0)
476 self.assertEqual(round(95.0, -1), 100.0)
477 self.assertEqual(round(12325.0, -1), 12330.0)
478
479 self.assertEqual(round(350.0, -2), 400.0)
480 self.assertEqual(round(450.0, -2), 500.0)
481
482 self.assertAlmostEqual(round(0.5e21, -21), 1e21)
483 self.assertAlmostEqual(round(1.5e21, -21), 2e21)
484 self.assertAlmostEqual(round(2.5e21, -21), 3e21)
485 self.assertAlmostEqual(round(5.5e21, -21), 6e21)
486 self.assertAlmostEqual(round(8.5e21, -21), 9e21)
487
488 self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
489 self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
490 self.assertAlmostEqual(round(0.5e22, -22), 1e22)
491 self.assertAlmostEqual(round(1.5e22, -22), 2e22)
492
Eric Smithf2bf0d22009-12-02 17:43:06 +0000493 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
494 "test requires IEEE 754 doubles")
495 def test_format_specials(self):
496 # Test formatting of nans and infs.
497
498 def test(fmt, value, expected):
499 # Test with both % and format().
500 self.assertEqual(fmt % value, expected, fmt)
501 if not '#' in fmt:
502 # Until issue 7094 is implemented, format() for floats doesn't
503 # support '#' formatting
504 fmt = fmt[1:] # strip off the %
505 self.assertEqual(format(value, fmt), expected, fmt)
506
507 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
508 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
509 pfmt = '%+' + fmt[1:]
510 sfmt = '% ' + fmt[1:]
511 test(fmt, INF, 'inf')
512 test(fmt, -INF, '-inf')
513 test(fmt, NAN, 'nan')
514 test(fmt, -NAN, 'nan')
515 # When asking for a sign, it's always provided. nans are
516 # always positive.
517 test(pfmt, INF, '+inf')
518 test(pfmt, -INF, '-inf')
519 test(pfmt, NAN, '+nan')
520 test(pfmt, -NAN, '+nan')
521 # When using ' ' for a sign code, only infs can be negative.
522 # Others have a space.
523 test(sfmt, INF, ' inf')
524 test(sfmt, -INF, '-inf')
525 test(sfmt, NAN, ' nan')
526 test(sfmt, -NAN, ' nan')
527
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000528
Christian Heimes0a8143f2007-12-18 23:22:54 +0000529# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000530# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000531class InfNanTest(unittest.TestCase):
532 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000533 self.assertTrue(isinf(float("inf")))
534 self.assertTrue(isinf(float("+inf")))
535 self.assertTrue(isinf(float("-inf")))
536 self.assertTrue(isinf(float("infinity")))
537 self.assertTrue(isinf(float("+infinity")))
538 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000539
540 self.assertEqual(repr(float("inf")), "inf")
541 self.assertEqual(repr(float("+inf")), "inf")
542 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000543 self.assertEqual(repr(float("infinity")), "inf")
544 self.assertEqual(repr(float("+infinity")), "inf")
545 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000546
547 self.assertEqual(repr(float("INF")), "inf")
548 self.assertEqual(repr(float("+Inf")), "inf")
549 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000550 self.assertEqual(repr(float("Infinity")), "inf")
551 self.assertEqual(repr(float("+iNfInItY")), "inf")
552 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000553
554 self.assertEqual(str(float("inf")), "inf")
555 self.assertEqual(str(float("+inf")), "inf")
556 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000557 self.assertEqual(str(float("infinity")), "inf")
558 self.assertEqual(str(float("+infinity")), "inf")
559 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000560
561 self.assertRaises(ValueError, float, "info")
562 self.assertRaises(ValueError, float, "+info")
563 self.assertRaises(ValueError, float, "-info")
564 self.assertRaises(ValueError, float, "in")
565 self.assertRaises(ValueError, float, "+in")
566 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000567 self.assertRaises(ValueError, float, "infinit")
568 self.assertRaises(ValueError, float, "+Infin")
569 self.assertRaises(ValueError, float, "-INFI")
570 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000571
572 def test_inf_as_str(self):
573 self.assertEqual(repr(1e300 * 1e300), "inf")
574 self.assertEqual(repr(-1e300 * 1e300), "-inf")
575
576 self.assertEqual(str(1e300 * 1e300), "inf")
577 self.assertEqual(str(-1e300 * 1e300), "-inf")
578
579 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000580 self.assertTrue(isnan(float("nan")))
581 self.assertTrue(isnan(float("+nan")))
582 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000583
584 self.assertEqual(repr(float("nan")), "nan")
585 self.assertEqual(repr(float("+nan")), "nan")
586 self.assertEqual(repr(float("-nan")), "nan")
587
588 self.assertEqual(repr(float("NAN")), "nan")
589 self.assertEqual(repr(float("+NAn")), "nan")
590 self.assertEqual(repr(float("-NaN")), "nan")
591
592 self.assertEqual(str(float("nan")), "nan")
593 self.assertEqual(str(float("+nan")), "nan")
594 self.assertEqual(str(float("-nan")), "nan")
595
596 self.assertRaises(ValueError, float, "nana")
597 self.assertRaises(ValueError, float, "+nana")
598 self.assertRaises(ValueError, float, "-nana")
599 self.assertRaises(ValueError, float, "na")
600 self.assertRaises(ValueError, float, "+na")
601 self.assertRaises(ValueError, float, "-na")
602
603 def test_nan_as_str(self):
604 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
605 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
606
607 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
608 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000609
Christian Heimes6f341092008-04-18 23:13:07 +0000610 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000611 self.assertTrue(NAN.is_nan())
612 self.assertFalse(INF.is_nan())
613 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000614
615 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000616 self.assertTrue(INF.is_inf())
617 self.assertFalse(NAN.is_inf())
618 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000619
Mark Dickinson7103aa42008-07-15 19:08:33 +0000620fromHex = float.fromhex
621toHex = float.hex
622class HexFloatTestCase(unittest.TestCase):
623 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
624 MIN = fromHex('0x1p-1022') # min normal
625 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
626 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
627
628 def identical(self, x, y):
629 # check that floats x and y are identical, or that both
630 # are NaNs
631 if isnan(x) or isnan(y):
632 if isnan(x) == isnan(y):
633 return
634 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
635 return
636 self.fail('%r not identical to %r' % (x, y))
637
638 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000639 self.identical(self.MIN, ldexp(1.0, -1022))
640 self.identical(self.TINY, ldexp(1.0, -1074))
641 self.identical(self.EPS, ldexp(1.0, -52))
642 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000643
644 def test_invalid_inputs(self):
645 invalid_inputs = [
646 'infi', # misspelt infinities and nans
647 '-Infinit',
648 '++inf',
649 '-+Inf',
650 '--nan',
651 '+-NaN',
652 'snan',
653 'NaNs',
654 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000655 'an',
656 'nf',
657 'nfinity',
658 'inity',
659 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000660 '0xnan',
661 '',
662 ' ',
663 'x1.0p0',
664 '0xX1.0p0',
665 '+ 0x1.0p0', # internal whitespace
666 '- 0x1.0p0',
667 '0 x1.0p0',
668 '0x 1.0p0',
669 '0x1 2.0p0',
670 '+0x1 .0p0',
671 '0x1. 0p0',
672 '-0x1.0 1p0',
673 '-0x1.0 p0',
674 '+0x1.0p +0',
675 '0x1.0p -0',
676 '0x1.0p 0',
677 '+0x1.0p+ 0',
678 '-0x1.0p- 0',
679 '++0x1.0p-0', # double signs
680 '--0x1.0p0',
681 '+-0x1.0p+0',
682 '-+0x1.0p0',
683 '0x1.0p++0',
684 '+0x1.0p+-0',
685 '-0x1.0p-+0',
686 '0x1.0p--0',
687 '0x1.0.p0',
688 '0x.p0', # no hex digits before or after point
689 '0x1,p0', # wrong decimal point character
690 '0x1pa',
691 u'0x1p\uff10', # fullwidth Unicode digits
692 u'\uff10x1p0',
693 u'0x\uff11p0',
694 u'0x1.\uff10p0',
695 '0x1p0 \n 0x2p0',
696 '0x1p0\0 0x1p0', # embedded null byte is not end of string
697 ]
698 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000699 try:
700 result = fromHex(x)
701 except ValueError:
702 pass
703 else:
704 self.fail('Expected float.fromhex(%r) to raise ValueError; '
705 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000706
707
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000708 def test_whitespace(self):
709 value_pairs = [
710 ('inf', INF),
711 ('-Infinity', -INF),
712 ('nan', NAN),
713 ('1.0', 1.0),
714 ('-0x.2', -0.125),
715 ('-0.0', -0.0)
716 ]
717 whitespace = [
718 '',
719 ' ',
720 '\t',
721 '\n',
722 '\n \t',
723 '\f',
724 '\v',
725 '\r'
726 ]
727 for inp, expected in value_pairs:
728 for lead in whitespace:
729 for trail in whitespace:
730 got = fromHex(lead + inp + trail)
731 self.identical(got, expected)
732
733
Mark Dickinson7103aa42008-07-15 19:08:33 +0000734 def test_from_hex(self):
735 MIN = self.MIN;
736 MAX = self.MAX;
737 TINY = self.TINY;
738 EPS = self.EPS;
739
740 # two spellings of infinity, with optional signs; case-insensitive
741 self.identical(fromHex('inf'), INF)
742 self.identical(fromHex('+Inf'), INF)
743 self.identical(fromHex('-INF'), -INF)
744 self.identical(fromHex('iNf'), INF)
745 self.identical(fromHex('Infinity'), INF)
746 self.identical(fromHex('+INFINITY'), INF)
747 self.identical(fromHex('-infinity'), -INF)
748 self.identical(fromHex('-iNFiNitY'), -INF)
749
750 # nans with optional sign; case insensitive
751 self.identical(fromHex('nan'), NAN)
752 self.identical(fromHex('+NaN'), NAN)
753 self.identical(fromHex('-NaN'), NAN)
754 self.identical(fromHex('-nAN'), NAN)
755
756 # variations in input format
757 self.identical(fromHex('1'), 1.0)
758 self.identical(fromHex('+1'), 1.0)
759 self.identical(fromHex('1.'), 1.0)
760 self.identical(fromHex('1.0'), 1.0)
761 self.identical(fromHex('1.0p0'), 1.0)
762 self.identical(fromHex('01'), 1.0)
763 self.identical(fromHex('01.'), 1.0)
764 self.identical(fromHex('0x1'), 1.0)
765 self.identical(fromHex('0x1.'), 1.0)
766 self.identical(fromHex('0x1.0'), 1.0)
767 self.identical(fromHex('+0x1.0'), 1.0)
768 self.identical(fromHex('0x1p0'), 1.0)
769 self.identical(fromHex('0X1p0'), 1.0)
770 self.identical(fromHex('0X1P0'), 1.0)
771 self.identical(fromHex('0x1P0'), 1.0)
772 self.identical(fromHex('0x1.p0'), 1.0)
773 self.identical(fromHex('0x1.0p0'), 1.0)
774 self.identical(fromHex('0x.1p4'), 1.0)
775 self.identical(fromHex('0x.1p04'), 1.0)
776 self.identical(fromHex('0x.1p004'), 1.0)
777 self.identical(fromHex('0x1p+0'), 1.0)
778 self.identical(fromHex('0x1P-0'), 1.0)
779 self.identical(fromHex('+0x1p0'), 1.0)
780 self.identical(fromHex('0x01p0'), 1.0)
781 self.identical(fromHex('0x1p00'), 1.0)
782 self.identical(fromHex(u'0x1p0'), 1.0)
783 self.identical(fromHex(' 0x1p0 '), 1.0)
784 self.identical(fromHex('\n 0x1p0'), 1.0)
785 self.identical(fromHex('0x1p0 \t'), 1.0)
786 self.identical(fromHex('0xap0'), 10.0)
787 self.identical(fromHex('0xAp0'), 10.0)
788 self.identical(fromHex('0xaP0'), 10.0)
789 self.identical(fromHex('0xAP0'), 10.0)
790 self.identical(fromHex('0xbep0'), 190.0)
791 self.identical(fromHex('0xBep0'), 190.0)
792 self.identical(fromHex('0xbEp0'), 190.0)
793 self.identical(fromHex('0XBE0P-4'), 190.0)
794 self.identical(fromHex('0xBEp0'), 190.0)
795 self.identical(fromHex('0xB.Ep4'), 190.0)
796 self.identical(fromHex('0x.BEp8'), 190.0)
797 self.identical(fromHex('0x.0BEp12'), 190.0)
798
799 # moving the point around
800 pi = fromHex('0x1.921fb54442d18p1')
801 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
802 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
803 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
804 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
805 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
806 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
807 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
808 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
809 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
810 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
811 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
812 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
813 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
814 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
815 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
816 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
817 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
818 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
819 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
820 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
821 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
822 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
823 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
824 # ...
825 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
826 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
827 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
828 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
829 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
830 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
831 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
832 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
833 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
834
835
836 # results that should overflow...
837 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
838 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
839 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
840 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
841 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
842 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
843 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
844 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
845 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
846 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
847 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
848 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
849 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
850 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
851 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
852 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
853 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
854 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
855 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
856
857 # ...and those that round to +-max float
858 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
859 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
860 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
861
862 # zeros
863 self.identical(fromHex('0x0p0'), 0.0)
864 self.identical(fromHex('0x0p1000'), 0.0)
865 self.identical(fromHex('-0x0p1023'), -0.0)
866 self.identical(fromHex('0X0p1024'), 0.0)
867 self.identical(fromHex('-0x0p1025'), -0.0)
868 self.identical(fromHex('0X0p2000'), 0.0)
869 self.identical(fromHex('0x0p123456789123456789'), 0.0)
870 self.identical(fromHex('-0X0p-0'), -0.0)
871 self.identical(fromHex('-0X0p-1000'), -0.0)
872 self.identical(fromHex('0x0p-1023'), 0.0)
873 self.identical(fromHex('-0X0p-1024'), -0.0)
874 self.identical(fromHex('-0x0p-1025'), -0.0)
875 self.identical(fromHex('-0x0p-1072'), -0.0)
876 self.identical(fromHex('0X0p-1073'), 0.0)
877 self.identical(fromHex('-0x0p-1074'), -0.0)
878 self.identical(fromHex('0x0p-1075'), 0.0)
879 self.identical(fromHex('0X0p-1076'), 0.0)
880 self.identical(fromHex('-0X0p-2000'), -0.0)
881 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
882
883 # values that should underflow to 0
884 self.identical(fromHex('0X1p-1075'), 0.0)
885 self.identical(fromHex('-0X1p-1075'), -0.0)
886 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
887 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
888 self.identical(fromHex('-0x1.1p-1075'), -TINY)
889 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
890
891 # check round-half-even is working correctly near 0 ...
892 self.identical(fromHex('0x1p-1076'), 0.0)
893 self.identical(fromHex('0X2p-1076'), 0.0)
894 self.identical(fromHex('0X3p-1076'), TINY)
895 self.identical(fromHex('0x4p-1076'), TINY)
896 self.identical(fromHex('0X5p-1076'), TINY)
897 self.identical(fromHex('0X6p-1076'), 2*TINY)
898 self.identical(fromHex('0x7p-1076'), 2*TINY)
899 self.identical(fromHex('0X8p-1076'), 2*TINY)
900 self.identical(fromHex('0X9p-1076'), 2*TINY)
901 self.identical(fromHex('0xap-1076'), 2*TINY)
902 self.identical(fromHex('0Xbp-1076'), 3*TINY)
903 self.identical(fromHex('0xcp-1076'), 3*TINY)
904 self.identical(fromHex('0Xdp-1076'), 3*TINY)
905 self.identical(fromHex('0Xep-1076'), 4*TINY)
906 self.identical(fromHex('0xfp-1076'), 4*TINY)
907 self.identical(fromHex('0x10p-1076'), 4*TINY)
908 self.identical(fromHex('-0x1p-1076'), -0.0)
909 self.identical(fromHex('-0X2p-1076'), -0.0)
910 self.identical(fromHex('-0x3p-1076'), -TINY)
911 self.identical(fromHex('-0X4p-1076'), -TINY)
912 self.identical(fromHex('-0x5p-1076'), -TINY)
913 self.identical(fromHex('-0x6p-1076'), -2*TINY)
914 self.identical(fromHex('-0X7p-1076'), -2*TINY)
915 self.identical(fromHex('-0X8p-1076'), -2*TINY)
916 self.identical(fromHex('-0X9p-1076'), -2*TINY)
917 self.identical(fromHex('-0Xap-1076'), -2*TINY)
918 self.identical(fromHex('-0xbp-1076'), -3*TINY)
919 self.identical(fromHex('-0xcp-1076'), -3*TINY)
920 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
921 self.identical(fromHex('-0xep-1076'), -4*TINY)
922 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
923 self.identical(fromHex('-0X10p-1076'), -4*TINY)
924
925 # ... and near MIN ...
926 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
927 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
928 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
929 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
930 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
931 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
932 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
933 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
934 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
935 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
936 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
937 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
938 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
939 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
940 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
941 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
942 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
943 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
944 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
945 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
946 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
947 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
948 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
949 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
950 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
951 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
952 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
953 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
954 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
955 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
956 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
957 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
958 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
959 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
960
961 # ... and near 1.0.
962 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
963 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
964 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
965 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
966 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
967 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
968 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
969 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
970 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
971 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
972 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
973 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
974 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
975 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
976 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
977 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
978 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
979 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
980 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
981 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
982 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
983 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
984 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
985 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
986 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
987 1.0)
988 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
989 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
990 1+EPS)
991 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
992 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
993 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
994 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
995 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
996 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
997 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
998 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
999 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1000 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1001 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1002 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1003 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1004 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1005 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1006 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1007 1.0+EPS)
1008 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1009 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1010 1.0+2*EPS)
1011 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1012 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1013 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1014 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1015 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1016 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1017 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1018 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1019
1020 def test_roundtrip(self):
1021 def roundtrip(x):
1022 return fromHex(toHex(x))
1023
1024 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1025 self.identical(x, roundtrip(x))
1026 self.identical(-x, roundtrip(-x))
1027
1028 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1029 import random
1030 for i in xrange(10000):
1031 e = random.randrange(-1200, 1200)
1032 m = random.random()
1033 s = random.choice([1.0, -1.0])
1034 try:
1035 x = s*ldexp(m, e)
1036 except OverflowError:
1037 pass
1038 else:
1039 self.identical(x, fromHex(toHex(x)))
1040
Christian Heimes6f341092008-04-18 23:13:07 +00001041
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001042def test_main():
1043 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +00001044 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001045 FormatFunctionsTestCase,
1046 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +00001047 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001048 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +00001049 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001050 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001051 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001052 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001053
1054if __name__ == '__main__':
1055 test_main()