blob: 05783b07602eeadfb74563acb20ccbb0e6976c35 [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes827b35c2007-12-10 22:19:17 +00003import os
Eric Smith0923d1d2009-04-16 20:16:10 +00004import sys
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Christian Heimes53876d92008-04-19 00:31:39 +00006import math
Mark Dickinson65fe25e2008-07-16 11:30:51 +00007from math import isinf, isnan, copysign, ldexp
Christian Heimes53876d92008-04-19 00:31:39 +00008import operator
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00009import random, fractions
Michael W. Hudsonba283e22005-05-27 15:23:20 +000010
Christian Heimes53876d92008-04-19 00:31:39 +000011INF = float("inf")
12NAN = float("nan")
Christian Heimes99170a52007-12-19 02:07:34 +000013
Eric Smith0923d1d2009-04-16 20:16:10 +000014#locate file with float format test values
15test_dir = os.path.dirname(__file__) or os.curdir
16format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
17
Christian Heimes81ee3ef2008-05-04 22:42:01 +000018class GeneralFloatCases(unittest.TestCase):
19
20 def test_float(self):
21 self.assertEqual(float(3.14), 3.14)
22 self.assertEqual(float(314), 314.0)
23 self.assertEqual(float(" 3.14 "), 3.14)
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +000024 self.assertEqual(float(b" 3.14 "), 3.14)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000025 self.assertRaises(ValueError, float, " 0x3.1 ")
26 self.assertRaises(ValueError, float, " -0x3.p-1 ")
27 self.assertRaises(ValueError, float, " +0x3.p-1 ")
28 self.assertRaises(ValueError, float, "++3.14")
29 self.assertRaises(ValueError, float, "+-3.14")
30 self.assertRaises(ValueError, float, "-+3.14")
31 self.assertRaises(ValueError, float, "--3.14")
Eric Smith0923d1d2009-04-16 20:16:10 +000032 self.assertRaises(ValueError, float, ".nan")
33 self.assertRaises(ValueError, float, "+.inf")
34 self.assertRaises(ValueError, float, ".")
35 self.assertRaises(ValueError, float, "-.")
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +000036 self.assertEqual(float(b" \u0663.\u0661\u0664 ".decode('raw-unicode-escape')), 3.14)
Mark Dickinsonee26c982009-10-27 22:13:18 +000037 # extra long strings should not be a problem
38 float(b'.' + b'1'*1000)
39 float('.' + '1'*1000)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000040
Benjamin Petersonee8712c2008-05-20 21:35:26 +000041 @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
Mark Dickinsonee26c982009-10-27 22:13:18 +000042
Christian Heimes81ee3ef2008-05-04 22:42:01 +000043 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 Petersond43029b2008-09-06 23:33:21 +000067 self.assertEqual(support.fcmp(float(" .25e-1 "), .025), 0)
Christian Heimes81ee3ef2008-05-04 22:42:01 +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 Peterson2808d3c2009-04-15 21:34:27 +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
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000100 self.assertAlmostEqual(float(Foo0()), 42.)
101 self.assertAlmostEqual(float(Foo1()), 42.)
102 self.assertAlmostEqual(float(Foo2()), 42.)
103 self.assertAlmostEqual(float(Foo3(21)), 42.)
104 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson2808d3c2009-04-15 21:34:27 +0000105 self.assertAlmostEqual(float(FooStr('8')), 9.)
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000106
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)),
113 ]:
114 self.assertEqual(f.as_integer_ratio(), ratio)
115
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)
121
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()))
135
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)
139
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000140 def test_float_containment(self):
141 floats = (INF, -INF, 0.0, 1.0, NAN)
142 for f in floats:
Georg Brandlab91fde2009-08-13 08:51:18 +0000143 self.assertTrue(f in [f], "'%r' not in []" % f)
144 self.assertTrue(f in (f,), "'%r' not in ()" % f)
145 self.assertTrue(f in {f}, "'%r' not in set()" % f)
146 self.assertTrue(f in {f: None}, "'%r' not in {}" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000147 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
Georg Brandlab91fde2009-08-13 08:51:18 +0000148 self.assertTrue(f in floats, "'%r' not in container" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000149
150 for f in floats:
151 # nonidentical containers, same type, same contents
Georg Brandlab91fde2009-08-13 08:51:18 +0000152 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f))
153 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f))
154 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f))
155 self.assertTrue({f : None} == {f: None}, "{%r : None} != "
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000156 "{%r : None}" % (f, f))
157
158 # identical containers
159 l, t, s, d = [f], (f,), {f}, {f: None}
Georg Brandlab91fde2009-08-13 08:51:18 +0000160 self.assertTrue(l == l, "[%r] not equal to itself" % f)
161 self.assertTrue(t == t, "(%r,) not equal to itself" % f)
162 self.assertTrue(s == s, "{%r} not equal to itself" % f)
163 self.assertTrue(d == d, "{%r : None} not equal to itself" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000164
165
166
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000167class FormatFunctionsTestCase(unittest.TestCase):
168
169 def setUp(self):
170 self.save_formats = {'double':float.__getformat__('double'),
171 'float':float.__getformat__('float')}
172
173 def tearDown(self):
174 float.__setformat__('double', self.save_formats['double'])
175 float.__setformat__('float', self.save_formats['float'])
176
177 def test_getformat(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000178 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000179 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Georg Brandlab91fde2009-08-13 08:51:18 +0000180 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000181 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
182 self.assertRaises(ValueError, float.__getformat__, 'chicken')
183 self.assertRaises(TypeError, float.__getformat__, 1)
184
185 def test_setformat(self):
186 for t in 'double', 'float':
187 float.__setformat__(t, 'unknown')
188 if self.save_formats[t] == 'IEEE, big-endian':
189 self.assertRaises(ValueError, float.__setformat__,
190 t, 'IEEE, little-endian')
191 elif self.save_formats[t] == 'IEEE, little-endian':
192 self.assertRaises(ValueError, float.__setformat__,
193 t, 'IEEE, big-endian')
194 else:
195 self.assertRaises(ValueError, float.__setformat__,
196 t, 'IEEE, big-endian')
197 self.assertRaises(ValueError, float.__setformat__,
198 t, 'IEEE, little-endian')
199 self.assertRaises(ValueError, float.__setformat__,
200 t, 'chicken')
201 self.assertRaises(ValueError, float.__setformat__,
202 'chicken', 'unknown')
203
Guido van Rossum2be161d2007-05-15 20:43:51 +0000204BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000205LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000206BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000207LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000208
Guido van Rossum2be161d2007-05-15 20:43:51 +0000209BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000210LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000211BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000212LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000213
214# on non-IEEE platforms, attempting to unpack a bit pattern
215# representing an infinity or a NaN should raise an exception.
216
217class UnknownFormatTestCase(unittest.TestCase):
218 def setUp(self):
219 self.save_formats = {'double':float.__getformat__('double'),
220 'float':float.__getformat__('float')}
221 float.__setformat__('double', 'unknown')
222 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000223
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000224 def tearDown(self):
225 float.__setformat__('double', self.save_formats['double'])
226 float.__setformat__('float', self.save_formats['float'])
227
228 def test_double_specials_dont_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 self.assertRaises(ValueError, struct.unpack, fmt, data)
234
235 def test_float_specials_dont_unpack(self):
236 for fmt, data in [('>f', BE_FLOAT_INF),
237 ('>f', BE_FLOAT_NAN),
238 ('<f', LE_FLOAT_INF),
239 ('<f', LE_FLOAT_NAN)]:
240 self.assertRaises(ValueError, struct.unpack, fmt, data)
241
242
243# on an IEEE platform, all we guarantee is that bit patterns
244# representing infinities or NaNs do not raise an exception; all else
245# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +0000246# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000247
248class IEEEFormatTestCase(unittest.TestCase):
249 if float.__getformat__("double").startswith("IEEE"):
250 def test_double_specials_do_unpack(self):
251 for fmt, data in [('>d', BE_DOUBLE_INF),
252 ('>d', BE_DOUBLE_NAN),
253 ('<d', LE_DOUBLE_INF),
254 ('<d', LE_DOUBLE_NAN)]:
255 struct.unpack(fmt, data)
256
257 if float.__getformat__("float").startswith("IEEE"):
258 def test_float_specials_do_unpack(self):
259 for fmt, data in [('>f', BE_FLOAT_INF),
260 ('>f', BE_FLOAT_NAN),
261 ('<f', LE_FLOAT_INF),
262 ('<f', LE_FLOAT_NAN)]:
263 struct.unpack(fmt, data)
264
Guido van Rossum04110fb2007-08-24 16:32:05 +0000265 if float.__getformat__("double").startswith("IEEE"):
266 def test_negative_zero(self):
267 import math
268 def pos_pos():
269 return 0.0, math.atan2(0.0, -1)
270 def pos_neg():
271 return 0.0, math.atan2(-0.0, -1)
272 def neg_pos():
273 return -0.0, math.atan2(0.0, -1)
274 def neg_neg():
275 return -0.0, math.atan2(-0.0, -1)
276 self.assertEquals(pos_pos(), neg_pos())
277 self.assertEquals(pos_neg(), neg_neg())
278
Eric Smith8c663262007-08-25 02:26:07 +0000279class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000280 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000281 # these should be rewritten to use both format(x, spec) and
282 # x.__format__(spec)
283
284 self.assertEqual(format(0.0, 'f'), '0.000000')
285
286 # the default is 'g', except for empty format spec
287 self.assertEqual(format(0.0, ''), '0.0')
288 self.assertEqual(format(0.01, ''), '0.01')
289 self.assertEqual(format(0.01, 'g'), '0.01')
290
Eric Smith63376222009-05-05 14:04:18 +0000291 # empty presentation type should format in the same way as str
292 # (issue 5920)
293 x = 100/7.
294 self.assertEqual(format(x, ''), str(x))
295 self.assertEqual(format(x, '-'), str(x))
296 self.assertEqual(format(x, '>'), str(x))
297 self.assertEqual(format(x, '2'), str(x))
Eric Smith8c663262007-08-25 02:26:07 +0000298
299 self.assertEqual(format(1.0, 'f'), '1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000300
301 self.assertEqual(format(-1.0, 'f'), '-1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000302
303 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
304 self.assertEqual(format(-1.0, ' f'), '-1.000000')
305 self.assertEqual(format( 1.0, '+f'), '+1.000000')
306 self.assertEqual(format(-1.0, '+f'), '-1.000000')
307
308 # % formatting
309 self.assertEqual(format(-1.0, '%'), '-100.000000%')
310
311 # conversion to string should fail
312 self.assertRaises(ValueError, format, 3.0, "s")
313
Eric Smith7b69c6c2008-01-27 21:07:59 +0000314 # other format specifiers shouldn't work on floats,
315 # in particular int specifiers
316 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
317 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
318 if not format_spec in 'eEfFgGn%':
319 self.assertRaises(ValueError, format, 0.0, format_spec)
320 self.assertRaises(ValueError, format, 1.0, format_spec)
321 self.assertRaises(ValueError, format, -1.0, format_spec)
322 self.assertRaises(ValueError, format, 1e100, format_spec)
323 self.assertRaises(ValueError, format, -1e100, format_spec)
324 self.assertRaises(ValueError, format, 1e-100, format_spec)
325 self.assertRaises(ValueError, format, -1e-100, format_spec)
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000326
Eric Smith741191f2009-05-06 13:08:15 +0000327 # issue 3382
328 self.assertEqual(format(NAN, 'f'), 'nan')
329 self.assertEqual(format(NAN, 'F'), 'NAN')
330 self.assertEqual(format(INF, 'f'), 'inf')
331 self.assertEqual(format(INF, 'F'), 'INF')
332
Eric Smith0923d1d2009-04-16 20:16:10 +0000333 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
334 "test requires IEEE 754 doubles")
335 def test_format_testfile(self):
336 for line in open(format_testfile):
337 if line.startswith('--'):
338 continue
339 line = line.strip()
340 if not line:
341 continue
342
343 lhs, rhs = map(str.strip, line.split('->'))
344 fmt, arg = lhs.split()
345 self.assertEqual(fmt % float(arg), rhs)
346 self.assertEqual(fmt % -float(arg), '-' + rhs)
347
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000348 def test_issue5864(self):
349 self.assertEquals(format(123.456, '.4'), '123.5')
350 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
351 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
352
Mark Dickinson7efad9e2009-04-17 20:59:58 +0000353class ReprTestCase(unittest.TestCase):
354 def test_repr(self):
355 floats_file = open(os.path.join(os.path.split(__file__)[0],
356 'floating_points.txt'))
357 for line in floats_file:
358 line = line.strip()
359 if not line or line.startswith('#'):
360 continue
361 v = eval(line)
362 self.assertEqual(v, eval(repr(v)))
363 floats_file.close()
364
Eric Smith0923d1d2009-04-16 20:16:10 +0000365 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
366 "applies only when using short float repr style")
367 def test_short_repr(self):
368 # test short float repr introduced in Python 3.1. One aspect
369 # of this repr is that we get some degree of str -> float ->
370 # str roundtripping. In particular, for any numeric string
371 # containing 15 or fewer significant digits, those exact same
372 # digits (modulo trailing zeros) should appear in the output.
373 # No more repr(0.03) -> "0.029999999999999999"!
374
375 test_strings = [
376 # output always includes *either* a decimal point and at
377 # least one digit after that point, or an exponent.
378 '0.0',
379 '1.0',
380 '0.01',
381 '0.02',
382 '0.03',
383 '0.04',
384 '0.05',
385 '1.23456789',
386 '10.0',
387 '100.0',
388 # values >= 1e16 get an exponent...
389 '1000000000000000.0',
390 '9999999999999990.0',
391 '1e+16',
392 '1e+17',
393 # ... and so do values < 1e-4
394 '0.001',
395 '0.001001',
396 '0.00010000000000001',
397 '0.0001',
398 '9.999999999999e-05',
399 '1e-05',
400 # values designed to provoke failure if the FPU rounding
401 # precision isn't set correctly
402 '8.72293771110361e+25',
403 '7.47005307342313e+26',
404 '2.86438000439698e+28',
405 '8.89142905246179e+28',
406 '3.08578087079232e+35',
407 ]
408
409 for s in test_strings:
410 negs = '-'+s
411 self.assertEqual(s, repr(float(s)))
412 self.assertEqual(negs, repr(float(negs)))
413
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000414class RoundTestCase(unittest.TestCase):
415 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
416 "test requires IEEE 754 doubles")
417 def test_inf_nan(self):
418 self.assertRaises(OverflowError, round, INF)
419 self.assertRaises(OverflowError, round, -INF)
420 self.assertRaises(ValueError, round, NAN)
421
422 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
423 "test requires IEEE 754 doubles")
424 def test_large_n(self):
425 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
426 self.assertEqual(round(123.456, n), 123.456)
427 self.assertEqual(round(-123.456, n), -123.456)
428 self.assertEqual(round(1e300, n), 1e300)
429 self.assertEqual(round(1e-320, n), 1e-320)
430 self.assertEqual(round(1e150, 300), 1e150)
431 self.assertEqual(round(1e300, 307), 1e300)
432 self.assertEqual(round(-3.1415, 308), -3.1415)
433 self.assertEqual(round(1e150, 309), 1e150)
434 self.assertEqual(round(1.4e-315, 315), 1e-315)
435
436 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
437 "test requires IEEE 754 doubles")
438 def test_small_n(self):
439 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
440 self.assertEqual(round(123.456, n), 0.0)
441 self.assertEqual(round(-123.456, n), -0.0)
442 self.assertEqual(round(1e300, n), 0.0)
443 self.assertEqual(round(1e-320, n), 0.0)
444
445 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
446 "test requires IEEE 754 doubles")
447 def test_overflow(self):
448 self.assertRaises(OverflowError, round, 1.6e308, -308)
449 self.assertRaises(OverflowError, round, -1.7e308, -308)
450
451 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
452 "applies only when using short float repr style")
453 def test_previous_round_bugs(self):
454 # particular cases that have occurred in bug reports
455 self.assertEqual(round(562949953421312.5, 1),
456 562949953421312.5)
457 self.assertEqual(round(56294995342131.5, 3),
458 56294995342131.5)
459 # round-half-even
460 self.assertEqual(round(25.0, -1), 20.0)
461 self.assertEqual(round(35.0, -1), 40.0)
462 self.assertEqual(round(45.0, -1), 40.0)
463 self.assertEqual(round(55.0, -1), 60.0)
464 self.assertEqual(round(65.0, -1), 60.0)
465 self.assertEqual(round(75.0, -1), 80.0)
466 self.assertEqual(round(85.0, -1), 80.0)
467 self.assertEqual(round(95.0, -1), 100.0)
468
469 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
470 "applies only when using short float repr style")
471 def test_matches_float_format(self):
472 # round should give the same results as float formatting
473 for i in range(500):
474 x = i/1000.
475 self.assertEqual(float(format(x, '.0f')), round(x, 0))
476 self.assertEqual(float(format(x, '.1f')), round(x, 1))
477 self.assertEqual(float(format(x, '.2f')), round(x, 2))
478 self.assertEqual(float(format(x, '.3f')), round(x, 3))
479
480 for i in range(5, 5000, 10):
481 x = i/1000.
482 self.assertEqual(float(format(x, '.0f')), round(x, 0))
483 self.assertEqual(float(format(x, '.1f')), round(x, 1))
484 self.assertEqual(float(format(x, '.2f')), round(x, 2))
485 self.assertEqual(float(format(x, '.3f')), round(x, 3))
486
487 for i in range(500):
488 x = random.random()
489 self.assertEqual(float(format(x, '.0f')), round(x, 0))
490 self.assertEqual(float(format(x, '.1f')), round(x, 1))
491 self.assertEqual(float(format(x, '.2f')), round(x, 2))
492 self.assertEqual(float(format(x, '.3f')), round(x, 3))
493
494
495
Christian Heimes99170a52007-12-19 02:07:34 +0000496# Beginning with Python 2.6 float has cross platform compatible
Georg Brandl2ee470f2008-07-16 12:55:28 +0000497# ways to create and represent inf and nan
Christian Heimes99170a52007-12-19 02:07:34 +0000498class InfNanTest(unittest.TestCase):
499 def test_inf_from_str(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000500 self.assertTrue(isinf(float("inf")))
501 self.assertTrue(isinf(float("+inf")))
502 self.assertTrue(isinf(float("-inf")))
503 self.assertTrue(isinf(float("infinity")))
504 self.assertTrue(isinf(float("+infinity")))
505 self.assertTrue(isinf(float("-infinity")))
Christian Heimes99170a52007-12-19 02:07:34 +0000506
507 self.assertEqual(repr(float("inf")), "inf")
508 self.assertEqual(repr(float("+inf")), "inf")
509 self.assertEqual(repr(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000510 self.assertEqual(repr(float("infinity")), "inf")
511 self.assertEqual(repr(float("+infinity")), "inf")
512 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000513
514 self.assertEqual(repr(float("INF")), "inf")
515 self.assertEqual(repr(float("+Inf")), "inf")
516 self.assertEqual(repr(float("-iNF")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000517 self.assertEqual(repr(float("Infinity")), "inf")
518 self.assertEqual(repr(float("+iNfInItY")), "inf")
519 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000520
521 self.assertEqual(str(float("inf")), "inf")
522 self.assertEqual(str(float("+inf")), "inf")
523 self.assertEqual(str(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000524 self.assertEqual(str(float("infinity")), "inf")
525 self.assertEqual(str(float("+infinity")), "inf")
526 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000527
528 self.assertRaises(ValueError, float, "info")
529 self.assertRaises(ValueError, float, "+info")
530 self.assertRaises(ValueError, float, "-info")
531 self.assertRaises(ValueError, float, "in")
532 self.assertRaises(ValueError, float, "+in")
533 self.assertRaises(ValueError, float, "-in")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000534 self.assertRaises(ValueError, float, "infinit")
535 self.assertRaises(ValueError, float, "+Infin")
536 self.assertRaises(ValueError, float, "-INFI")
537 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes99170a52007-12-19 02:07:34 +0000538
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000539 self.assertRaises(ValueError, float, "++Inf")
540 self.assertRaises(ValueError, float, "-+inf")
541 self.assertRaises(ValueError, float, "+-infinity")
542 self.assertRaises(ValueError, float, "--Infinity")
543
Christian Heimes99170a52007-12-19 02:07:34 +0000544 def test_inf_as_str(self):
545 self.assertEqual(repr(1e300 * 1e300), "inf")
546 self.assertEqual(repr(-1e300 * 1e300), "-inf")
547
548 self.assertEqual(str(1e300 * 1e300), "inf")
549 self.assertEqual(str(-1e300 * 1e300), "-inf")
550
551 def test_nan_from_str(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000552 self.assertTrue(isnan(float("nan")))
553 self.assertTrue(isnan(float("+nan")))
554 self.assertTrue(isnan(float("-nan")))
Christian Heimes99170a52007-12-19 02:07:34 +0000555
556 self.assertEqual(repr(float("nan")), "nan")
557 self.assertEqual(repr(float("+nan")), "nan")
558 self.assertEqual(repr(float("-nan")), "nan")
559
560 self.assertEqual(repr(float("NAN")), "nan")
561 self.assertEqual(repr(float("+NAn")), "nan")
562 self.assertEqual(repr(float("-NaN")), "nan")
563
564 self.assertEqual(str(float("nan")), "nan")
565 self.assertEqual(str(float("+nan")), "nan")
566 self.assertEqual(str(float("-nan")), "nan")
567
568 self.assertRaises(ValueError, float, "nana")
569 self.assertRaises(ValueError, float, "+nana")
570 self.assertRaises(ValueError, float, "-nana")
571 self.assertRaises(ValueError, float, "na")
572 self.assertRaises(ValueError, float, "+na")
573 self.assertRaises(ValueError, float, "-na")
574
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000575 self.assertRaises(ValueError, float, "++nan")
576 self.assertRaises(ValueError, float, "-+NAN")
577 self.assertRaises(ValueError, float, "+-NaN")
578 self.assertRaises(ValueError, float, "--nAn")
579
Christian Heimes99170a52007-12-19 02:07:34 +0000580 def test_nan_as_str(self):
581 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
582 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
583
584 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
585 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000586
Christian Heimes53876d92008-04-19 00:31:39 +0000587 def notest_float_nan(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000588 self.assertTrue(NAN.is_nan())
589 self.assertFalse(INF.is_nan())
590 self.assertFalse((0.).is_nan())
Christian Heimes53876d92008-04-19 00:31:39 +0000591
592 def notest_float_inf(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000593 self.assertTrue(INF.is_inf())
594 self.assertFalse(NAN.is_inf())
595 self.assertFalse((0.).is_inf())
Christian Heimes53876d92008-04-19 00:31:39 +0000596
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000597fromHex = float.fromhex
598toHex = float.hex
599class HexFloatTestCase(unittest.TestCase):
600 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
601 MIN = fromHex('0x1p-1022') # min normal
602 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
603 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
604
605 def identical(self, x, y):
606 # check that floats x and y are identical, or that both
607 # are NaNs
608 if isnan(x) or isnan(y):
609 if isnan(x) == isnan(y):
610 return
611 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
612 return
613 self.fail('%r not identical to %r' % (x, y))
614
615 def test_ends(self):
Mark Dickinson38bbc482008-07-16 11:32:23 +0000616 self.identical(self.MIN, ldexp(1.0, -1022))
617 self.identical(self.TINY, ldexp(1.0, -1074))
618 self.identical(self.EPS, ldexp(1.0, -52))
619 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000620
621 def test_invalid_inputs(self):
622 invalid_inputs = [
623 'infi', # misspelt infinities and nans
624 '-Infinit',
625 '++inf',
626 '-+Inf',
627 '--nan',
628 '+-NaN',
629 'snan',
630 'NaNs',
631 'nna',
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000632 'an',
633 'nf',
634 'nfinity',
635 'inity',
636 'iinity',
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000637 '0xnan',
638 '',
639 ' ',
640 'x1.0p0',
641 '0xX1.0p0',
642 '+ 0x1.0p0', # internal whitespace
643 '- 0x1.0p0',
644 '0 x1.0p0',
645 '0x 1.0p0',
646 '0x1 2.0p0',
647 '+0x1 .0p0',
648 '0x1. 0p0',
649 '-0x1.0 1p0',
650 '-0x1.0 p0',
651 '+0x1.0p +0',
652 '0x1.0p -0',
653 '0x1.0p 0',
654 '+0x1.0p+ 0',
655 '-0x1.0p- 0',
656 '++0x1.0p-0', # double signs
657 '--0x1.0p0',
658 '+-0x1.0p+0',
659 '-+0x1.0p0',
660 '0x1.0p++0',
661 '+0x1.0p+-0',
662 '-0x1.0p-+0',
663 '0x1.0p--0',
664 '0x1.0.p0',
665 '0x.p0', # no hex digits before or after point
666 '0x1,p0', # wrong decimal point character
667 '0x1pa',
668 '0x1p\uff10', # fullwidth Unicode digits
669 '\uff10x1p0',
670 '0x\uff11p0',
671 '0x1.\uff10p0',
672 '0x1p0 \n 0x2p0',
673 '0x1p0\0 0x1p0', # embedded null byte is not end of string
674 ]
675 for x in invalid_inputs:
Mark Dickinson589b7952008-08-21 20:05:56 +0000676 try:
677 result = fromHex(x)
678 except ValueError:
679 pass
680 else:
681 self.fail('Expected float.fromhex(%r) to raise ValueError; '
682 'got %r instead' % (x, result))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000683
684
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000685 def test_whitespace(self):
686 value_pairs = [
687 ('inf', INF),
688 ('-Infinity', -INF),
689 ('nan', NAN),
690 ('1.0', 1.0),
691 ('-0x.2', -0.125),
692 ('-0.0', -0.0)
693 ]
694 whitespace = [
695 '',
696 ' ',
697 '\t',
698 '\n',
699 '\n \t',
700 '\f',
701 '\v',
702 '\r'
703 ]
704 for inp, expected in value_pairs:
705 for lead in whitespace:
706 for trail in whitespace:
707 got = fromHex(lead + inp + trail)
708 self.identical(got, expected)
709
710
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000711 def test_from_hex(self):
712 MIN = self.MIN;
713 MAX = self.MAX;
714 TINY = self.TINY;
715 EPS = self.EPS;
716
717 # two spellings of infinity, with optional signs; case-insensitive
718 self.identical(fromHex('inf'), INF)
719 self.identical(fromHex('+Inf'), INF)
720 self.identical(fromHex('-INF'), -INF)
721 self.identical(fromHex('iNf'), INF)
722 self.identical(fromHex('Infinity'), INF)
723 self.identical(fromHex('+INFINITY'), INF)
724 self.identical(fromHex('-infinity'), -INF)
725 self.identical(fromHex('-iNFiNitY'), -INF)
726
727 # nans with optional sign; case insensitive
728 self.identical(fromHex('nan'), NAN)
729 self.identical(fromHex('+NaN'), NAN)
730 self.identical(fromHex('-NaN'), NAN)
731 self.identical(fromHex('-nAN'), NAN)
732
733 # variations in input format
734 self.identical(fromHex('1'), 1.0)
735 self.identical(fromHex('+1'), 1.0)
736 self.identical(fromHex('1.'), 1.0)
737 self.identical(fromHex('1.0'), 1.0)
738 self.identical(fromHex('1.0p0'), 1.0)
739 self.identical(fromHex('01'), 1.0)
740 self.identical(fromHex('01.'), 1.0)
741 self.identical(fromHex('0x1'), 1.0)
742 self.identical(fromHex('0x1.'), 1.0)
743 self.identical(fromHex('0x1.0'), 1.0)
744 self.identical(fromHex('+0x1.0'), 1.0)
745 self.identical(fromHex('0x1p0'), 1.0)
746 self.identical(fromHex('0X1p0'), 1.0)
747 self.identical(fromHex('0X1P0'), 1.0)
748 self.identical(fromHex('0x1P0'), 1.0)
749 self.identical(fromHex('0x1.p0'), 1.0)
750 self.identical(fromHex('0x1.0p0'), 1.0)
751 self.identical(fromHex('0x.1p4'), 1.0)
752 self.identical(fromHex('0x.1p04'), 1.0)
753 self.identical(fromHex('0x.1p004'), 1.0)
754 self.identical(fromHex('0x1p+0'), 1.0)
755 self.identical(fromHex('0x1P-0'), 1.0)
756 self.identical(fromHex('+0x1p0'), 1.0)
757 self.identical(fromHex('0x01p0'), 1.0)
758 self.identical(fromHex('0x1p00'), 1.0)
759 self.identical(fromHex(' 0x1p0 '), 1.0)
760 self.identical(fromHex('\n 0x1p0'), 1.0)
761 self.identical(fromHex('0x1p0 \t'), 1.0)
762 self.identical(fromHex('0xap0'), 10.0)
763 self.identical(fromHex('0xAp0'), 10.0)
764 self.identical(fromHex('0xaP0'), 10.0)
765 self.identical(fromHex('0xAP0'), 10.0)
766 self.identical(fromHex('0xbep0'), 190.0)
767 self.identical(fromHex('0xBep0'), 190.0)
768 self.identical(fromHex('0xbEp0'), 190.0)
769 self.identical(fromHex('0XBE0P-4'), 190.0)
770 self.identical(fromHex('0xBEp0'), 190.0)
771 self.identical(fromHex('0xB.Ep4'), 190.0)
772 self.identical(fromHex('0x.BEp8'), 190.0)
773 self.identical(fromHex('0x.0BEp12'), 190.0)
774
775 # moving the point around
776 pi = fromHex('0x1.921fb54442d18p1')
777 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
778 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
779 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
780 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
781 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
782 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
783 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
784 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
785 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
786 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
787 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
788 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
789 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
790 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
791 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
792 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
793 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
794 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
795 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
796 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
797 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
798 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
799 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
800 # ...
801 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
802 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
803 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
804 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
805 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
806 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
807 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
808 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
809 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
810
811
812 # results that should overflow...
813 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
814 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
815 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
816 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
817 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
818 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
819 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
820 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
821 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
822 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
823 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
824 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
825 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
826 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
827 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
828 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
829 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
830 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
831 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
832
833 # ...and those that round to +-max float
834 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
835 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
836 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
837
838 # zeros
839 self.identical(fromHex('0x0p0'), 0.0)
840 self.identical(fromHex('0x0p1000'), 0.0)
841 self.identical(fromHex('-0x0p1023'), -0.0)
842 self.identical(fromHex('0X0p1024'), 0.0)
843 self.identical(fromHex('-0x0p1025'), -0.0)
844 self.identical(fromHex('0X0p2000'), 0.0)
845 self.identical(fromHex('0x0p123456789123456789'), 0.0)
846 self.identical(fromHex('-0X0p-0'), -0.0)
847 self.identical(fromHex('-0X0p-1000'), -0.0)
848 self.identical(fromHex('0x0p-1023'), 0.0)
849 self.identical(fromHex('-0X0p-1024'), -0.0)
850 self.identical(fromHex('-0x0p-1025'), -0.0)
851 self.identical(fromHex('-0x0p-1072'), -0.0)
852 self.identical(fromHex('0X0p-1073'), 0.0)
853 self.identical(fromHex('-0x0p-1074'), -0.0)
854 self.identical(fromHex('0x0p-1075'), 0.0)
855 self.identical(fromHex('0X0p-1076'), 0.0)
856 self.identical(fromHex('-0X0p-2000'), -0.0)
857 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
858
859 # values that should underflow to 0
860 self.identical(fromHex('0X1p-1075'), 0.0)
861 self.identical(fromHex('-0X1p-1075'), -0.0)
862 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
863 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
864 self.identical(fromHex('-0x1.1p-1075'), -TINY)
865 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
866
867 # check round-half-even is working correctly near 0 ...
868 self.identical(fromHex('0x1p-1076'), 0.0)
869 self.identical(fromHex('0X2p-1076'), 0.0)
870 self.identical(fromHex('0X3p-1076'), TINY)
871 self.identical(fromHex('0x4p-1076'), TINY)
872 self.identical(fromHex('0X5p-1076'), TINY)
873 self.identical(fromHex('0X6p-1076'), 2*TINY)
874 self.identical(fromHex('0x7p-1076'), 2*TINY)
875 self.identical(fromHex('0X8p-1076'), 2*TINY)
876 self.identical(fromHex('0X9p-1076'), 2*TINY)
877 self.identical(fromHex('0xap-1076'), 2*TINY)
878 self.identical(fromHex('0Xbp-1076'), 3*TINY)
879 self.identical(fromHex('0xcp-1076'), 3*TINY)
880 self.identical(fromHex('0Xdp-1076'), 3*TINY)
881 self.identical(fromHex('0Xep-1076'), 4*TINY)
882 self.identical(fromHex('0xfp-1076'), 4*TINY)
883 self.identical(fromHex('0x10p-1076'), 4*TINY)
884 self.identical(fromHex('-0x1p-1076'), -0.0)
885 self.identical(fromHex('-0X2p-1076'), -0.0)
886 self.identical(fromHex('-0x3p-1076'), -TINY)
887 self.identical(fromHex('-0X4p-1076'), -TINY)
888 self.identical(fromHex('-0x5p-1076'), -TINY)
889 self.identical(fromHex('-0x6p-1076'), -2*TINY)
890 self.identical(fromHex('-0X7p-1076'), -2*TINY)
891 self.identical(fromHex('-0X8p-1076'), -2*TINY)
892 self.identical(fromHex('-0X9p-1076'), -2*TINY)
893 self.identical(fromHex('-0Xap-1076'), -2*TINY)
894 self.identical(fromHex('-0xbp-1076'), -3*TINY)
895 self.identical(fromHex('-0xcp-1076'), -3*TINY)
896 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
897 self.identical(fromHex('-0xep-1076'), -4*TINY)
898 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
899 self.identical(fromHex('-0X10p-1076'), -4*TINY)
900
901 # ... and near MIN ...
902 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
903 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
904 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
905 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
906 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
907 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
908 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
909 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
910 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
911 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
912 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
913 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
914 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
915 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
916 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
917 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
918 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
919 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
920 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
921 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
922 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
923 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
924 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
925 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
926 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
927 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
928 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
929 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
930 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
931 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
932 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
933 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
934 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
935 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
936
937 # ... and near 1.0.
938 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
939 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
940 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
941 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
942 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
943 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
944 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
945 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
946 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
947 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
948 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
949 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
950 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
951 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
952 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
953 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
954 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
955 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
956 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
957 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
958 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
959 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
960 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
961 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
962 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
963 1.0)
964 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
965 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
966 1+EPS)
967 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
968 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
969 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
970 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
971 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
972 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
973 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
974 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
975 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
976 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
977 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
978 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
979 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
980 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
981 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
982 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
983 1.0+EPS)
984 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
985 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
986 1.0+2*EPS)
987 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
988 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
989 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
990 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
991 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
992 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
993 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
994 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
995
996 def test_roundtrip(self):
997 def roundtrip(x):
998 return fromHex(toHex(x))
999
1000 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1001 self.identical(x, roundtrip(x))
1002 self.identical(-x, roundtrip(-x))
1003
1004 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1005 import random
1006 for i in range(10000):
1007 e = random.randrange(-1200, 1200)
1008 m = random.random()
1009 s = random.choice([1.0, -1.0])
1010 try:
1011 x = s*ldexp(m, e)
1012 except OverflowError:
1013 pass
1014 else:
1015 self.identical(x, fromHex(toHex(x)))
1016
Christian Heimes53876d92008-04-19 00:31:39 +00001017
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001018def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001019 support.run_unittest(
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00001020 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001021 FormatFunctionsTestCase,
1022 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +00001023 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +00001024 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001025 ReprTestCase,
Mark Dickinsone6a076d2009-04-18 11:48:33 +00001026 RoundTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001027 InfNanTest,
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001028 HexFloatTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +00001029 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001030
1031if __name__ == '__main__':
1032 test_main()