blob: 3ad140288190e3afeb2516a889217be0b499161a [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
493
Christian Heimes0a8143f2007-12-18 23:22:54 +0000494# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000495# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000496class InfNanTest(unittest.TestCase):
497 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000498 self.assertTrue(isinf(float("inf")))
499 self.assertTrue(isinf(float("+inf")))
500 self.assertTrue(isinf(float("-inf")))
501 self.assertTrue(isinf(float("infinity")))
502 self.assertTrue(isinf(float("+infinity")))
503 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000504
505 self.assertEqual(repr(float("inf")), "inf")
506 self.assertEqual(repr(float("+inf")), "inf")
507 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000508 self.assertEqual(repr(float("infinity")), "inf")
509 self.assertEqual(repr(float("+infinity")), "inf")
510 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000511
512 self.assertEqual(repr(float("INF")), "inf")
513 self.assertEqual(repr(float("+Inf")), "inf")
514 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000515 self.assertEqual(repr(float("Infinity")), "inf")
516 self.assertEqual(repr(float("+iNfInItY")), "inf")
517 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000518
519 self.assertEqual(str(float("inf")), "inf")
520 self.assertEqual(str(float("+inf")), "inf")
521 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000522 self.assertEqual(str(float("infinity")), "inf")
523 self.assertEqual(str(float("+infinity")), "inf")
524 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000525
526 self.assertRaises(ValueError, float, "info")
527 self.assertRaises(ValueError, float, "+info")
528 self.assertRaises(ValueError, float, "-info")
529 self.assertRaises(ValueError, float, "in")
530 self.assertRaises(ValueError, float, "+in")
531 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000532 self.assertRaises(ValueError, float, "infinit")
533 self.assertRaises(ValueError, float, "+Infin")
534 self.assertRaises(ValueError, float, "-INFI")
535 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000536
537 def test_inf_as_str(self):
538 self.assertEqual(repr(1e300 * 1e300), "inf")
539 self.assertEqual(repr(-1e300 * 1e300), "-inf")
540
541 self.assertEqual(str(1e300 * 1e300), "inf")
542 self.assertEqual(str(-1e300 * 1e300), "-inf")
543
544 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000545 self.assertTrue(isnan(float("nan")))
546 self.assertTrue(isnan(float("+nan")))
547 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000548
549 self.assertEqual(repr(float("nan")), "nan")
550 self.assertEqual(repr(float("+nan")), "nan")
551 self.assertEqual(repr(float("-nan")), "nan")
552
553 self.assertEqual(repr(float("NAN")), "nan")
554 self.assertEqual(repr(float("+NAn")), "nan")
555 self.assertEqual(repr(float("-NaN")), "nan")
556
557 self.assertEqual(str(float("nan")), "nan")
558 self.assertEqual(str(float("+nan")), "nan")
559 self.assertEqual(str(float("-nan")), "nan")
560
561 self.assertRaises(ValueError, float, "nana")
562 self.assertRaises(ValueError, float, "+nana")
563 self.assertRaises(ValueError, float, "-nana")
564 self.assertRaises(ValueError, float, "na")
565 self.assertRaises(ValueError, float, "+na")
566 self.assertRaises(ValueError, float, "-na")
567
568 def test_nan_as_str(self):
569 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
570 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
571
572 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
573 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000574
Christian Heimes6f341092008-04-18 23:13:07 +0000575 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000576 self.assertTrue(NAN.is_nan())
577 self.assertFalse(INF.is_nan())
578 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000579
580 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000581 self.assertTrue(INF.is_inf())
582 self.assertFalse(NAN.is_inf())
583 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000584
Mark Dickinson7103aa42008-07-15 19:08:33 +0000585fromHex = float.fromhex
586toHex = float.hex
587class HexFloatTestCase(unittest.TestCase):
588 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
589 MIN = fromHex('0x1p-1022') # min normal
590 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
591 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
592
593 def identical(self, x, y):
594 # check that floats x and y are identical, or that both
595 # are NaNs
596 if isnan(x) or isnan(y):
597 if isnan(x) == isnan(y):
598 return
599 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
600 return
601 self.fail('%r not identical to %r' % (x, y))
602
603 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000604 self.identical(self.MIN, ldexp(1.0, -1022))
605 self.identical(self.TINY, ldexp(1.0, -1074))
606 self.identical(self.EPS, ldexp(1.0, -52))
607 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000608
609 def test_invalid_inputs(self):
610 invalid_inputs = [
611 'infi', # misspelt infinities and nans
612 '-Infinit',
613 '++inf',
614 '-+Inf',
615 '--nan',
616 '+-NaN',
617 'snan',
618 'NaNs',
619 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000620 'an',
621 'nf',
622 'nfinity',
623 'inity',
624 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000625 '0xnan',
626 '',
627 ' ',
628 'x1.0p0',
629 '0xX1.0p0',
630 '+ 0x1.0p0', # internal whitespace
631 '- 0x1.0p0',
632 '0 x1.0p0',
633 '0x 1.0p0',
634 '0x1 2.0p0',
635 '+0x1 .0p0',
636 '0x1. 0p0',
637 '-0x1.0 1p0',
638 '-0x1.0 p0',
639 '+0x1.0p +0',
640 '0x1.0p -0',
641 '0x1.0p 0',
642 '+0x1.0p+ 0',
643 '-0x1.0p- 0',
644 '++0x1.0p-0', # double signs
645 '--0x1.0p0',
646 '+-0x1.0p+0',
647 '-+0x1.0p0',
648 '0x1.0p++0',
649 '+0x1.0p+-0',
650 '-0x1.0p-+0',
651 '0x1.0p--0',
652 '0x1.0.p0',
653 '0x.p0', # no hex digits before or after point
654 '0x1,p0', # wrong decimal point character
655 '0x1pa',
656 u'0x1p\uff10', # fullwidth Unicode digits
657 u'\uff10x1p0',
658 u'0x\uff11p0',
659 u'0x1.\uff10p0',
660 '0x1p0 \n 0x2p0',
661 '0x1p0\0 0x1p0', # embedded null byte is not end of string
662 ]
663 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000664 try:
665 result = fromHex(x)
666 except ValueError:
667 pass
668 else:
669 self.fail('Expected float.fromhex(%r) to raise ValueError; '
670 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000671
672
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000673 def test_whitespace(self):
674 value_pairs = [
675 ('inf', INF),
676 ('-Infinity', -INF),
677 ('nan', NAN),
678 ('1.0', 1.0),
679 ('-0x.2', -0.125),
680 ('-0.0', -0.0)
681 ]
682 whitespace = [
683 '',
684 ' ',
685 '\t',
686 '\n',
687 '\n \t',
688 '\f',
689 '\v',
690 '\r'
691 ]
692 for inp, expected in value_pairs:
693 for lead in whitespace:
694 for trail in whitespace:
695 got = fromHex(lead + inp + trail)
696 self.identical(got, expected)
697
698
Mark Dickinson7103aa42008-07-15 19:08:33 +0000699 def test_from_hex(self):
700 MIN = self.MIN;
701 MAX = self.MAX;
702 TINY = self.TINY;
703 EPS = self.EPS;
704
705 # two spellings of infinity, with optional signs; case-insensitive
706 self.identical(fromHex('inf'), INF)
707 self.identical(fromHex('+Inf'), INF)
708 self.identical(fromHex('-INF'), -INF)
709 self.identical(fromHex('iNf'), INF)
710 self.identical(fromHex('Infinity'), INF)
711 self.identical(fromHex('+INFINITY'), INF)
712 self.identical(fromHex('-infinity'), -INF)
713 self.identical(fromHex('-iNFiNitY'), -INF)
714
715 # nans with optional sign; case insensitive
716 self.identical(fromHex('nan'), NAN)
717 self.identical(fromHex('+NaN'), NAN)
718 self.identical(fromHex('-NaN'), NAN)
719 self.identical(fromHex('-nAN'), NAN)
720
721 # variations in input format
722 self.identical(fromHex('1'), 1.0)
723 self.identical(fromHex('+1'), 1.0)
724 self.identical(fromHex('1.'), 1.0)
725 self.identical(fromHex('1.0'), 1.0)
726 self.identical(fromHex('1.0p0'), 1.0)
727 self.identical(fromHex('01'), 1.0)
728 self.identical(fromHex('01.'), 1.0)
729 self.identical(fromHex('0x1'), 1.0)
730 self.identical(fromHex('0x1.'), 1.0)
731 self.identical(fromHex('0x1.0'), 1.0)
732 self.identical(fromHex('+0x1.0'), 1.0)
733 self.identical(fromHex('0x1p0'), 1.0)
734 self.identical(fromHex('0X1p0'), 1.0)
735 self.identical(fromHex('0X1P0'), 1.0)
736 self.identical(fromHex('0x1P0'), 1.0)
737 self.identical(fromHex('0x1.p0'), 1.0)
738 self.identical(fromHex('0x1.0p0'), 1.0)
739 self.identical(fromHex('0x.1p4'), 1.0)
740 self.identical(fromHex('0x.1p04'), 1.0)
741 self.identical(fromHex('0x.1p004'), 1.0)
742 self.identical(fromHex('0x1p+0'), 1.0)
743 self.identical(fromHex('0x1P-0'), 1.0)
744 self.identical(fromHex('+0x1p0'), 1.0)
745 self.identical(fromHex('0x01p0'), 1.0)
746 self.identical(fromHex('0x1p00'), 1.0)
747 self.identical(fromHex(u'0x1p0'), 1.0)
748 self.identical(fromHex(' 0x1p0 '), 1.0)
749 self.identical(fromHex('\n 0x1p0'), 1.0)
750 self.identical(fromHex('0x1p0 \t'), 1.0)
751 self.identical(fromHex('0xap0'), 10.0)
752 self.identical(fromHex('0xAp0'), 10.0)
753 self.identical(fromHex('0xaP0'), 10.0)
754 self.identical(fromHex('0xAP0'), 10.0)
755 self.identical(fromHex('0xbep0'), 190.0)
756 self.identical(fromHex('0xBep0'), 190.0)
757 self.identical(fromHex('0xbEp0'), 190.0)
758 self.identical(fromHex('0XBE0P-4'), 190.0)
759 self.identical(fromHex('0xBEp0'), 190.0)
760 self.identical(fromHex('0xB.Ep4'), 190.0)
761 self.identical(fromHex('0x.BEp8'), 190.0)
762 self.identical(fromHex('0x.0BEp12'), 190.0)
763
764 # moving the point around
765 pi = fromHex('0x1.921fb54442d18p1')
766 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
767 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
768 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
769 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
770 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
771 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
772 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
773 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
774 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
775 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
776 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
777 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
778 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
779 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
780 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
781 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
782 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
783 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
784 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
785 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
786 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
787 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
788 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
789 # ...
790 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
791 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
792 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
793 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
794 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
795 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
796 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
797 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
798 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
799
800
801 # results that should overflow...
802 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
803 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
804 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
805 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
806 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
807 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
808 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
809 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
810 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
811 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
812 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
813 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
814 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
815 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
816 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
817 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
818 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
819 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
820 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
821
822 # ...and those that round to +-max float
823 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
824 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
825 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
826
827 # zeros
828 self.identical(fromHex('0x0p0'), 0.0)
829 self.identical(fromHex('0x0p1000'), 0.0)
830 self.identical(fromHex('-0x0p1023'), -0.0)
831 self.identical(fromHex('0X0p1024'), 0.0)
832 self.identical(fromHex('-0x0p1025'), -0.0)
833 self.identical(fromHex('0X0p2000'), 0.0)
834 self.identical(fromHex('0x0p123456789123456789'), 0.0)
835 self.identical(fromHex('-0X0p-0'), -0.0)
836 self.identical(fromHex('-0X0p-1000'), -0.0)
837 self.identical(fromHex('0x0p-1023'), 0.0)
838 self.identical(fromHex('-0X0p-1024'), -0.0)
839 self.identical(fromHex('-0x0p-1025'), -0.0)
840 self.identical(fromHex('-0x0p-1072'), -0.0)
841 self.identical(fromHex('0X0p-1073'), 0.0)
842 self.identical(fromHex('-0x0p-1074'), -0.0)
843 self.identical(fromHex('0x0p-1075'), 0.0)
844 self.identical(fromHex('0X0p-1076'), 0.0)
845 self.identical(fromHex('-0X0p-2000'), -0.0)
846 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
847
848 # values that should underflow to 0
849 self.identical(fromHex('0X1p-1075'), 0.0)
850 self.identical(fromHex('-0X1p-1075'), -0.0)
851 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
852 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
853 self.identical(fromHex('-0x1.1p-1075'), -TINY)
854 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
855
856 # check round-half-even is working correctly near 0 ...
857 self.identical(fromHex('0x1p-1076'), 0.0)
858 self.identical(fromHex('0X2p-1076'), 0.0)
859 self.identical(fromHex('0X3p-1076'), TINY)
860 self.identical(fromHex('0x4p-1076'), TINY)
861 self.identical(fromHex('0X5p-1076'), TINY)
862 self.identical(fromHex('0X6p-1076'), 2*TINY)
863 self.identical(fromHex('0x7p-1076'), 2*TINY)
864 self.identical(fromHex('0X8p-1076'), 2*TINY)
865 self.identical(fromHex('0X9p-1076'), 2*TINY)
866 self.identical(fromHex('0xap-1076'), 2*TINY)
867 self.identical(fromHex('0Xbp-1076'), 3*TINY)
868 self.identical(fromHex('0xcp-1076'), 3*TINY)
869 self.identical(fromHex('0Xdp-1076'), 3*TINY)
870 self.identical(fromHex('0Xep-1076'), 4*TINY)
871 self.identical(fromHex('0xfp-1076'), 4*TINY)
872 self.identical(fromHex('0x10p-1076'), 4*TINY)
873 self.identical(fromHex('-0x1p-1076'), -0.0)
874 self.identical(fromHex('-0X2p-1076'), -0.0)
875 self.identical(fromHex('-0x3p-1076'), -TINY)
876 self.identical(fromHex('-0X4p-1076'), -TINY)
877 self.identical(fromHex('-0x5p-1076'), -TINY)
878 self.identical(fromHex('-0x6p-1076'), -2*TINY)
879 self.identical(fromHex('-0X7p-1076'), -2*TINY)
880 self.identical(fromHex('-0X8p-1076'), -2*TINY)
881 self.identical(fromHex('-0X9p-1076'), -2*TINY)
882 self.identical(fromHex('-0Xap-1076'), -2*TINY)
883 self.identical(fromHex('-0xbp-1076'), -3*TINY)
884 self.identical(fromHex('-0xcp-1076'), -3*TINY)
885 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
886 self.identical(fromHex('-0xep-1076'), -4*TINY)
887 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
888 self.identical(fromHex('-0X10p-1076'), -4*TINY)
889
890 # ... and near MIN ...
891 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
892 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
893 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
894 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
895 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
896 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
897 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
898 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
899 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
900 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
901 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
902 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
903 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
904 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
905 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
906 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
907 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
908 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
909 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
910 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
911 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
912 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
913 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
914 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
915 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
916 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
917 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
918 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
919 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
920 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
921 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
922 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
923 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
924 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
925
926 # ... and near 1.0.
927 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
928 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
929 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
930 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
931 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
932 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
933 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
934 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
935 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
936 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
937 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
938 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
939 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
940 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
941 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
942 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
943 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
944 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
945 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
946 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
947 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
948 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
949 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
950 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
951 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
952 1.0)
953 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
954 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
955 1+EPS)
956 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
957 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
958 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
959 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
960 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
961 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
962 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
963 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
964 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
965 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
966 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
967 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
968 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
969 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
970 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
971 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
972 1.0+EPS)
973 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
974 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
975 1.0+2*EPS)
976 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
977 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
978 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
979 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
980 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
981 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
982 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
983 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
984
985 def test_roundtrip(self):
986 def roundtrip(x):
987 return fromHex(toHex(x))
988
989 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
990 self.identical(x, roundtrip(x))
991 self.identical(-x, roundtrip(-x))
992
993 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
994 import random
995 for i in xrange(10000):
996 e = random.randrange(-1200, 1200)
997 m = random.random()
998 s = random.choice([1.0, -1.0])
999 try:
1000 x = s*ldexp(m, e)
1001 except OverflowError:
1002 pass
1003 else:
1004 self.identical(x, fromHex(toHex(x)))
1005
Christian Heimes6f341092008-04-18 23:13:07 +00001006
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001007def test_main():
1008 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +00001009 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001010 FormatFunctionsTestCase,
1011 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +00001012 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001013 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +00001014 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001015 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001016 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001017 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001018
1019if __name__ == '__main__':
1020 test_main()