blob: af5e13c7addf1d8a5246be82ea90c626616b9792 [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)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000037
Benjamin Petersonee8712c2008-05-20 21:35:26 +000038 @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
Christian Heimes81ee3ef2008-05-04 22:42:01 +000039 def test_float_with_comma(self):
40 # set locale to something that doesn't use '.' for the decimal point
41 # float must not accept the locale specific decimal point but
42 # it still has to accept the normal python syntac
43 import locale
44 if not locale.localeconv()['decimal_point'] == ',':
45 return
46
47 self.assertEqual(float(" 3.14 "), 3.14)
48 self.assertEqual(float("+3.14 "), 3.14)
49 self.assertEqual(float("-3.14 "), -3.14)
50 self.assertEqual(float(".14 "), .14)
51 self.assertEqual(float("3. "), 3.0)
52 self.assertEqual(float("3.e3 "), 3000.0)
53 self.assertEqual(float("3.2e3 "), 3200.0)
54 self.assertEqual(float("2.5e-1 "), 0.25)
55 self.assertEqual(float("5e-1"), 0.5)
56 self.assertRaises(ValueError, float, " 3,14 ")
57 self.assertRaises(ValueError, float, " +3,14 ")
58 self.assertRaises(ValueError, float, " -3,14 ")
59 self.assertRaises(ValueError, float, " 0x3.1 ")
60 self.assertRaises(ValueError, float, " -0x3.p-1 ")
61 self.assertRaises(ValueError, float, " +0x3.p-1 ")
62 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersond43029b2008-09-06 23:33:21 +000063 self.assertEqual(support.fcmp(float(" .25e-1 "), .025), 0)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000064
65 def test_floatconversion(self):
66 # Make sure that calls to __float__() work properly
67 class Foo0:
68 def __float__(self):
69 return 42.
70
71 class Foo1(object):
72 def __float__(self):
73 return 42.
74
75 class Foo2(float):
76 def __float__(self):
77 return 42.
78
79 class Foo3(float):
80 def __new__(cls, value=0.):
81 return float.__new__(cls, 2*value)
82
83 def __float__(self):
84 return self
85
86 class Foo4(float):
87 def __float__(self):
88 return 42
89
Benjamin Peterson2808d3c2009-04-15 21:34:27 +000090 # Issue 5759: __float__ not called on str subclasses (though it is on
91 # unicode subclasses).
92 class FooStr(str):
93 def __float__(self):
94 return float(str(self)) + 1
95
Christian Heimes81ee3ef2008-05-04 22:42:01 +000096 self.assertAlmostEqual(float(Foo0()), 42.)
97 self.assertAlmostEqual(float(Foo1()), 42.)
98 self.assertAlmostEqual(float(Foo2()), 42.)
99 self.assertAlmostEqual(float(Foo3(21)), 42.)
100 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson2808d3c2009-04-15 21:34:27 +0000101 self.assertAlmostEqual(float(FooStr('8')), 9.)
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000102
103 def test_floatasratio(self):
104 for f, ratio in [
105 (0.875, (7, 8)),
106 (-0.875, (-7, 8)),
107 (0.0, (0, 1)),
108 (11.5, (23, 2)),
109 ]:
110 self.assertEqual(f.as_integer_ratio(), ratio)
111
112 for i in range(10000):
113 f = random.random()
114 f *= 10 ** random.randint(-100, 100)
115 n, d = f.as_integer_ratio()
116 self.assertEqual(float(n).__truediv__(d), f)
117
118 R = fractions.Fraction
119 self.assertEqual(R(0, 1),
120 R(*float(0.0).as_integer_ratio()))
121 self.assertEqual(R(5, 2),
122 R(*float(2.5).as_integer_ratio()))
123 self.assertEqual(R(1, 2),
124 R(*float(0.5).as_integer_ratio()))
125 self.assertEqual(R(4728779608739021, 2251799813685248),
126 R(*float(2.1).as_integer_ratio()))
127 self.assertEqual(R(-4728779608739021, 2251799813685248),
128 R(*float(-2.1).as_integer_ratio()))
129 self.assertEqual(R(-2100, 1),
130 R(*float(-2100.0).as_integer_ratio()))
131
132 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
133 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
134 self.assertRaises(ValueError, float('nan').as_integer_ratio)
135
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000136 def test_float_containment(self):
137 floats = (INF, -INF, 0.0, 1.0, NAN)
138 for f in floats:
Georg Brandlab91fde2009-08-13 08:51:18 +0000139 self.assertTrue(f in [f], "'%r' not in []" % f)
140 self.assertTrue(f in (f,), "'%r' not in ()" % f)
141 self.assertTrue(f in {f}, "'%r' not in set()" % f)
142 self.assertTrue(f in {f: None}, "'%r' not in {}" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000143 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
Georg Brandlab91fde2009-08-13 08:51:18 +0000144 self.assertTrue(f in floats, "'%r' not in container" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000145
146 for f in floats:
147 # nonidentical containers, same type, same contents
Georg Brandlab91fde2009-08-13 08:51:18 +0000148 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f))
149 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f))
150 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f))
151 self.assertTrue({f : None} == {f: None}, "{%r : None} != "
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000152 "{%r : None}" % (f, f))
153
154 # identical containers
155 l, t, s, d = [f], (f,), {f}, {f: None}
Georg Brandlab91fde2009-08-13 08:51:18 +0000156 self.assertTrue(l == l, "[%r] not equal to itself" % f)
157 self.assertTrue(t == t, "(%r,) not equal to itself" % f)
158 self.assertTrue(s == s, "{%r} not equal to itself" % f)
159 self.assertTrue(d == d, "{%r : None} not equal to itself" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000160
161
162
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000163class FormatFunctionsTestCase(unittest.TestCase):
164
165 def setUp(self):
166 self.save_formats = {'double':float.__getformat__('double'),
167 'float':float.__getformat__('float')}
168
169 def tearDown(self):
170 float.__setformat__('double', self.save_formats['double'])
171 float.__setformat__('float', self.save_formats['float'])
172
173 def test_getformat(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000174 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000175 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Georg Brandlab91fde2009-08-13 08:51:18 +0000176 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000177 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
178 self.assertRaises(ValueError, float.__getformat__, 'chicken')
179 self.assertRaises(TypeError, float.__getformat__, 1)
180
181 def test_setformat(self):
182 for t in 'double', 'float':
183 float.__setformat__(t, 'unknown')
184 if self.save_formats[t] == 'IEEE, big-endian':
185 self.assertRaises(ValueError, float.__setformat__,
186 t, 'IEEE, little-endian')
187 elif self.save_formats[t] == 'IEEE, little-endian':
188 self.assertRaises(ValueError, float.__setformat__,
189 t, 'IEEE, big-endian')
190 else:
191 self.assertRaises(ValueError, float.__setformat__,
192 t, 'IEEE, big-endian')
193 self.assertRaises(ValueError, float.__setformat__,
194 t, 'IEEE, little-endian')
195 self.assertRaises(ValueError, float.__setformat__,
196 t, 'chicken')
197 self.assertRaises(ValueError, float.__setformat__,
198 'chicken', 'unknown')
199
Guido van Rossum2be161d2007-05-15 20:43:51 +0000200BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000201LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000202BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000203LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000204
Guido van Rossum2be161d2007-05-15 20:43:51 +0000205BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000206LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000207BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000208LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000209
210# on non-IEEE platforms, attempting to unpack a bit pattern
211# representing an infinity or a NaN should raise an exception.
212
213class UnknownFormatTestCase(unittest.TestCase):
214 def setUp(self):
215 self.save_formats = {'double':float.__getformat__('double'),
216 'float':float.__getformat__('float')}
217 float.__setformat__('double', 'unknown')
218 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000219
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000220 def tearDown(self):
221 float.__setformat__('double', self.save_formats['double'])
222 float.__setformat__('float', self.save_formats['float'])
223
224 def test_double_specials_dont_unpack(self):
225 for fmt, data in [('>d', BE_DOUBLE_INF),
226 ('>d', BE_DOUBLE_NAN),
227 ('<d', LE_DOUBLE_INF),
228 ('<d', LE_DOUBLE_NAN)]:
229 self.assertRaises(ValueError, struct.unpack, fmt, data)
230
231 def test_float_specials_dont_unpack(self):
232 for fmt, data in [('>f', BE_FLOAT_INF),
233 ('>f', BE_FLOAT_NAN),
234 ('<f', LE_FLOAT_INF),
235 ('<f', LE_FLOAT_NAN)]:
236 self.assertRaises(ValueError, struct.unpack, fmt, data)
237
238
239# on an IEEE platform, all we guarantee is that bit patterns
240# representing infinities or NaNs do not raise an exception; all else
241# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +0000242# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000243
244class IEEEFormatTestCase(unittest.TestCase):
245 if float.__getformat__("double").startswith("IEEE"):
246 def test_double_specials_do_unpack(self):
247 for fmt, data in [('>d', BE_DOUBLE_INF),
248 ('>d', BE_DOUBLE_NAN),
249 ('<d', LE_DOUBLE_INF),
250 ('<d', LE_DOUBLE_NAN)]:
251 struct.unpack(fmt, data)
252
253 if float.__getformat__("float").startswith("IEEE"):
254 def test_float_specials_do_unpack(self):
255 for fmt, data in [('>f', BE_FLOAT_INF),
256 ('>f', BE_FLOAT_NAN),
257 ('<f', LE_FLOAT_INF),
258 ('<f', LE_FLOAT_NAN)]:
259 struct.unpack(fmt, data)
260
Guido van Rossum04110fb2007-08-24 16:32:05 +0000261 if float.__getformat__("double").startswith("IEEE"):
262 def test_negative_zero(self):
263 import math
264 def pos_pos():
265 return 0.0, math.atan2(0.0, -1)
266 def pos_neg():
267 return 0.0, math.atan2(-0.0, -1)
268 def neg_pos():
269 return -0.0, math.atan2(0.0, -1)
270 def neg_neg():
271 return -0.0, math.atan2(-0.0, -1)
272 self.assertEquals(pos_pos(), neg_pos())
273 self.assertEquals(pos_neg(), neg_neg())
274
Eric Smith8c663262007-08-25 02:26:07 +0000275class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000276 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000277 # these should be rewritten to use both format(x, spec) and
278 # x.__format__(spec)
279
280 self.assertEqual(format(0.0, 'f'), '0.000000')
281
282 # the default is 'g', except for empty format spec
283 self.assertEqual(format(0.0, ''), '0.0')
284 self.assertEqual(format(0.01, ''), '0.01')
285 self.assertEqual(format(0.01, 'g'), '0.01')
286
Eric Smith63376222009-05-05 14:04:18 +0000287 # empty presentation type should format in the same way as str
288 # (issue 5920)
289 x = 100/7.
290 self.assertEqual(format(x, ''), str(x))
291 self.assertEqual(format(x, '-'), str(x))
292 self.assertEqual(format(x, '>'), str(x))
293 self.assertEqual(format(x, '2'), str(x))
Eric Smith8c663262007-08-25 02:26:07 +0000294
295 self.assertEqual(format(1.0, 'f'), '1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000296
297 self.assertEqual(format(-1.0, 'f'), '-1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000298
299 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
300 self.assertEqual(format(-1.0, ' f'), '-1.000000')
301 self.assertEqual(format( 1.0, '+f'), '+1.000000')
302 self.assertEqual(format(-1.0, '+f'), '-1.000000')
303
304 # % formatting
305 self.assertEqual(format(-1.0, '%'), '-100.000000%')
306
307 # conversion to string should fail
308 self.assertRaises(ValueError, format, 3.0, "s")
309
Eric Smith7b69c6c2008-01-27 21:07:59 +0000310 # other format specifiers shouldn't work on floats,
311 # in particular int specifiers
312 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
313 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
314 if not format_spec in 'eEfFgGn%':
315 self.assertRaises(ValueError, format, 0.0, format_spec)
316 self.assertRaises(ValueError, format, 1.0, format_spec)
317 self.assertRaises(ValueError, format, -1.0, format_spec)
318 self.assertRaises(ValueError, format, 1e100, format_spec)
319 self.assertRaises(ValueError, format, -1e100, format_spec)
320 self.assertRaises(ValueError, format, 1e-100, format_spec)
321 self.assertRaises(ValueError, format, -1e-100, format_spec)
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000322
Eric Smith741191f2009-05-06 13:08:15 +0000323 # issue 3382
324 self.assertEqual(format(NAN, 'f'), 'nan')
325 self.assertEqual(format(NAN, 'F'), 'NAN')
326 self.assertEqual(format(INF, 'f'), 'inf')
327 self.assertEqual(format(INF, 'F'), 'INF')
328
Eric Smith0923d1d2009-04-16 20:16:10 +0000329 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
330 "test requires IEEE 754 doubles")
331 def test_format_testfile(self):
332 for line in open(format_testfile):
333 if line.startswith('--'):
334 continue
335 line = line.strip()
336 if not line:
337 continue
338
339 lhs, rhs = map(str.strip, line.split('->'))
340 fmt, arg = lhs.split()
341 self.assertEqual(fmt % float(arg), rhs)
342 self.assertEqual(fmt % -float(arg), '-' + rhs)
343
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000344 def test_issue5864(self):
345 self.assertEquals(format(123.456, '.4'), '123.5')
346 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
347 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
348
Mark Dickinson7efad9e2009-04-17 20:59:58 +0000349class ReprTestCase(unittest.TestCase):
350 def test_repr(self):
351 floats_file = open(os.path.join(os.path.split(__file__)[0],
352 'floating_points.txt'))
353 for line in floats_file:
354 line = line.strip()
355 if not line or line.startswith('#'):
356 continue
357 v = eval(line)
358 self.assertEqual(v, eval(repr(v)))
359 floats_file.close()
360
Eric Smith0923d1d2009-04-16 20:16:10 +0000361 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
362 "applies only when using short float repr style")
363 def test_short_repr(self):
364 # test short float repr introduced in Python 3.1. One aspect
365 # of this repr is that we get some degree of str -> float ->
366 # str roundtripping. In particular, for any numeric string
367 # containing 15 or fewer significant digits, those exact same
368 # digits (modulo trailing zeros) should appear in the output.
369 # No more repr(0.03) -> "0.029999999999999999"!
370
371 test_strings = [
372 # output always includes *either* a decimal point and at
373 # least one digit after that point, or an exponent.
374 '0.0',
375 '1.0',
376 '0.01',
377 '0.02',
378 '0.03',
379 '0.04',
380 '0.05',
381 '1.23456789',
382 '10.0',
383 '100.0',
384 # values >= 1e16 get an exponent...
385 '1000000000000000.0',
386 '9999999999999990.0',
387 '1e+16',
388 '1e+17',
389 # ... and so do values < 1e-4
390 '0.001',
391 '0.001001',
392 '0.00010000000000001',
393 '0.0001',
394 '9.999999999999e-05',
395 '1e-05',
396 # values designed to provoke failure if the FPU rounding
397 # precision isn't set correctly
398 '8.72293771110361e+25',
399 '7.47005307342313e+26',
400 '2.86438000439698e+28',
401 '8.89142905246179e+28',
402 '3.08578087079232e+35',
403 ]
404
405 for s in test_strings:
406 negs = '-'+s
407 self.assertEqual(s, repr(float(s)))
408 self.assertEqual(negs, repr(float(negs)))
409
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000410class RoundTestCase(unittest.TestCase):
411 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
412 "test requires IEEE 754 doubles")
413 def test_inf_nan(self):
414 self.assertRaises(OverflowError, round, INF)
415 self.assertRaises(OverflowError, round, -INF)
416 self.assertRaises(ValueError, round, NAN)
417
418 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
419 "test requires IEEE 754 doubles")
420 def test_large_n(self):
421 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
422 self.assertEqual(round(123.456, n), 123.456)
423 self.assertEqual(round(-123.456, n), -123.456)
424 self.assertEqual(round(1e300, n), 1e300)
425 self.assertEqual(round(1e-320, n), 1e-320)
426 self.assertEqual(round(1e150, 300), 1e150)
427 self.assertEqual(round(1e300, 307), 1e300)
428 self.assertEqual(round(-3.1415, 308), -3.1415)
429 self.assertEqual(round(1e150, 309), 1e150)
430 self.assertEqual(round(1.4e-315, 315), 1e-315)
431
432 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
433 "test requires IEEE 754 doubles")
434 def test_small_n(self):
435 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
436 self.assertEqual(round(123.456, n), 0.0)
437 self.assertEqual(round(-123.456, n), -0.0)
438 self.assertEqual(round(1e300, n), 0.0)
439 self.assertEqual(round(1e-320, n), 0.0)
440
441 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
442 "test requires IEEE 754 doubles")
443 def test_overflow(self):
444 self.assertRaises(OverflowError, round, 1.6e308, -308)
445 self.assertRaises(OverflowError, round, -1.7e308, -308)
446
447 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
448 "applies only when using short float repr style")
449 def test_previous_round_bugs(self):
450 # particular cases that have occurred in bug reports
451 self.assertEqual(round(562949953421312.5, 1),
452 562949953421312.5)
453 self.assertEqual(round(56294995342131.5, 3),
454 56294995342131.5)
455 # round-half-even
456 self.assertEqual(round(25.0, -1), 20.0)
457 self.assertEqual(round(35.0, -1), 40.0)
458 self.assertEqual(round(45.0, -1), 40.0)
459 self.assertEqual(round(55.0, -1), 60.0)
460 self.assertEqual(round(65.0, -1), 60.0)
461 self.assertEqual(round(75.0, -1), 80.0)
462 self.assertEqual(round(85.0, -1), 80.0)
463 self.assertEqual(round(95.0, -1), 100.0)
464
465 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
466 "applies only when using short float repr style")
467 def test_matches_float_format(self):
468 # round should give the same results as float formatting
469 for i in range(500):
470 x = i/1000.
471 self.assertEqual(float(format(x, '.0f')), round(x, 0))
472 self.assertEqual(float(format(x, '.1f')), round(x, 1))
473 self.assertEqual(float(format(x, '.2f')), round(x, 2))
474 self.assertEqual(float(format(x, '.3f')), round(x, 3))
475
476 for i in range(5, 5000, 10):
477 x = i/1000.
478 self.assertEqual(float(format(x, '.0f')), round(x, 0))
479 self.assertEqual(float(format(x, '.1f')), round(x, 1))
480 self.assertEqual(float(format(x, '.2f')), round(x, 2))
481 self.assertEqual(float(format(x, '.3f')), round(x, 3))
482
483 for i in range(500):
484 x = random.random()
485 self.assertEqual(float(format(x, '.0f')), round(x, 0))
486 self.assertEqual(float(format(x, '.1f')), round(x, 1))
487 self.assertEqual(float(format(x, '.2f')), round(x, 2))
488 self.assertEqual(float(format(x, '.3f')), round(x, 3))
489
490
491
Christian Heimes99170a52007-12-19 02:07:34 +0000492# Beginning with Python 2.6 float has cross platform compatible
Georg Brandl2ee470f2008-07-16 12:55:28 +0000493# ways to create and represent inf and nan
Christian Heimes99170a52007-12-19 02:07:34 +0000494class InfNanTest(unittest.TestCase):
495 def test_inf_from_str(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000496 self.assertTrue(isinf(float("inf")))
497 self.assertTrue(isinf(float("+inf")))
498 self.assertTrue(isinf(float("-inf")))
499 self.assertTrue(isinf(float("infinity")))
500 self.assertTrue(isinf(float("+infinity")))
501 self.assertTrue(isinf(float("-infinity")))
Christian Heimes99170a52007-12-19 02:07:34 +0000502
503 self.assertEqual(repr(float("inf")), "inf")
504 self.assertEqual(repr(float("+inf")), "inf")
505 self.assertEqual(repr(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000506 self.assertEqual(repr(float("infinity")), "inf")
507 self.assertEqual(repr(float("+infinity")), "inf")
508 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000509
510 self.assertEqual(repr(float("INF")), "inf")
511 self.assertEqual(repr(float("+Inf")), "inf")
512 self.assertEqual(repr(float("-iNF")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000513 self.assertEqual(repr(float("Infinity")), "inf")
514 self.assertEqual(repr(float("+iNfInItY")), "inf")
515 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000516
517 self.assertEqual(str(float("inf")), "inf")
518 self.assertEqual(str(float("+inf")), "inf")
519 self.assertEqual(str(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000520 self.assertEqual(str(float("infinity")), "inf")
521 self.assertEqual(str(float("+infinity")), "inf")
522 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000523
524 self.assertRaises(ValueError, float, "info")
525 self.assertRaises(ValueError, float, "+info")
526 self.assertRaises(ValueError, float, "-info")
527 self.assertRaises(ValueError, float, "in")
528 self.assertRaises(ValueError, float, "+in")
529 self.assertRaises(ValueError, float, "-in")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000530 self.assertRaises(ValueError, float, "infinit")
531 self.assertRaises(ValueError, float, "+Infin")
532 self.assertRaises(ValueError, float, "-INFI")
533 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes99170a52007-12-19 02:07:34 +0000534
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000535 self.assertRaises(ValueError, float, "++Inf")
536 self.assertRaises(ValueError, float, "-+inf")
537 self.assertRaises(ValueError, float, "+-infinity")
538 self.assertRaises(ValueError, float, "--Infinity")
539
Christian Heimes99170a52007-12-19 02:07:34 +0000540 def test_inf_as_str(self):
541 self.assertEqual(repr(1e300 * 1e300), "inf")
542 self.assertEqual(repr(-1e300 * 1e300), "-inf")
543
544 self.assertEqual(str(1e300 * 1e300), "inf")
545 self.assertEqual(str(-1e300 * 1e300), "-inf")
546
547 def test_nan_from_str(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000548 self.assertTrue(isnan(float("nan")))
549 self.assertTrue(isnan(float("+nan")))
550 self.assertTrue(isnan(float("-nan")))
Christian Heimes99170a52007-12-19 02:07:34 +0000551
552 self.assertEqual(repr(float("nan")), "nan")
553 self.assertEqual(repr(float("+nan")), "nan")
554 self.assertEqual(repr(float("-nan")), "nan")
555
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(str(float("nan")), "nan")
561 self.assertEqual(str(float("+nan")), "nan")
562 self.assertEqual(str(float("-nan")), "nan")
563
564 self.assertRaises(ValueError, float, "nana")
565 self.assertRaises(ValueError, float, "+nana")
566 self.assertRaises(ValueError, float, "-nana")
567 self.assertRaises(ValueError, float, "na")
568 self.assertRaises(ValueError, float, "+na")
569 self.assertRaises(ValueError, float, "-na")
570
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000571 self.assertRaises(ValueError, float, "++nan")
572 self.assertRaises(ValueError, float, "-+NAN")
573 self.assertRaises(ValueError, float, "+-NaN")
574 self.assertRaises(ValueError, float, "--nAn")
575
Christian Heimes99170a52007-12-19 02:07:34 +0000576 def test_nan_as_str(self):
577 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
578 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
579
580 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
581 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000582
Christian Heimes53876d92008-04-19 00:31:39 +0000583 def notest_float_nan(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000584 self.assertTrue(NAN.is_nan())
585 self.assertFalse(INF.is_nan())
586 self.assertFalse((0.).is_nan())
Christian Heimes53876d92008-04-19 00:31:39 +0000587
588 def notest_float_inf(self):
Georg Brandlab91fde2009-08-13 08:51:18 +0000589 self.assertTrue(INF.is_inf())
590 self.assertFalse(NAN.is_inf())
591 self.assertFalse((0.).is_inf())
Christian Heimes53876d92008-04-19 00:31:39 +0000592
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000593fromHex = float.fromhex
594toHex = float.hex
595class HexFloatTestCase(unittest.TestCase):
596 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
597 MIN = fromHex('0x1p-1022') # min normal
598 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
599 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
600
601 def identical(self, x, y):
602 # check that floats x and y are identical, or that both
603 # are NaNs
604 if isnan(x) or isnan(y):
605 if isnan(x) == isnan(y):
606 return
607 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
608 return
609 self.fail('%r not identical to %r' % (x, y))
610
611 def test_ends(self):
Mark Dickinson38bbc482008-07-16 11:32:23 +0000612 self.identical(self.MIN, ldexp(1.0, -1022))
613 self.identical(self.TINY, ldexp(1.0, -1074))
614 self.identical(self.EPS, ldexp(1.0, -52))
615 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000616
617 def test_invalid_inputs(self):
618 invalid_inputs = [
619 'infi', # misspelt infinities and nans
620 '-Infinit',
621 '++inf',
622 '-+Inf',
623 '--nan',
624 '+-NaN',
625 'snan',
626 'NaNs',
627 'nna',
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000628 'an',
629 'nf',
630 'nfinity',
631 'inity',
632 'iinity',
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000633 '0xnan',
634 '',
635 ' ',
636 'x1.0p0',
637 '0xX1.0p0',
638 '+ 0x1.0p0', # internal whitespace
639 '- 0x1.0p0',
640 '0 x1.0p0',
641 '0x 1.0p0',
642 '0x1 2.0p0',
643 '+0x1 .0p0',
644 '0x1. 0p0',
645 '-0x1.0 1p0',
646 '-0x1.0 p0',
647 '+0x1.0p +0',
648 '0x1.0p -0',
649 '0x1.0p 0',
650 '+0x1.0p+ 0',
651 '-0x1.0p- 0',
652 '++0x1.0p-0', # double signs
653 '--0x1.0p0',
654 '+-0x1.0p+0',
655 '-+0x1.0p0',
656 '0x1.0p++0',
657 '+0x1.0p+-0',
658 '-0x1.0p-+0',
659 '0x1.0p--0',
660 '0x1.0.p0',
661 '0x.p0', # no hex digits before or after point
662 '0x1,p0', # wrong decimal point character
663 '0x1pa',
664 '0x1p\uff10', # fullwidth Unicode digits
665 '\uff10x1p0',
666 '0x\uff11p0',
667 '0x1.\uff10p0',
668 '0x1p0 \n 0x2p0',
669 '0x1p0\0 0x1p0', # embedded null byte is not end of string
670 ]
671 for x in invalid_inputs:
Mark Dickinson589b7952008-08-21 20:05:56 +0000672 try:
673 result = fromHex(x)
674 except ValueError:
675 pass
676 else:
677 self.fail('Expected float.fromhex(%r) to raise ValueError; '
678 'got %r instead' % (x, result))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000679
680
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000681 def test_whitespace(self):
682 value_pairs = [
683 ('inf', INF),
684 ('-Infinity', -INF),
685 ('nan', NAN),
686 ('1.0', 1.0),
687 ('-0x.2', -0.125),
688 ('-0.0', -0.0)
689 ]
690 whitespace = [
691 '',
692 ' ',
693 '\t',
694 '\n',
695 '\n \t',
696 '\f',
697 '\v',
698 '\r'
699 ]
700 for inp, expected in value_pairs:
701 for lead in whitespace:
702 for trail in whitespace:
703 got = fromHex(lead + inp + trail)
704 self.identical(got, expected)
705
706
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000707 def test_from_hex(self):
708 MIN = self.MIN;
709 MAX = self.MAX;
710 TINY = self.TINY;
711 EPS = self.EPS;
712
713 # two spellings of infinity, with optional signs; case-insensitive
714 self.identical(fromHex('inf'), INF)
715 self.identical(fromHex('+Inf'), INF)
716 self.identical(fromHex('-INF'), -INF)
717 self.identical(fromHex('iNf'), INF)
718 self.identical(fromHex('Infinity'), INF)
719 self.identical(fromHex('+INFINITY'), INF)
720 self.identical(fromHex('-infinity'), -INF)
721 self.identical(fromHex('-iNFiNitY'), -INF)
722
723 # nans with optional sign; case insensitive
724 self.identical(fromHex('nan'), NAN)
725 self.identical(fromHex('+NaN'), NAN)
726 self.identical(fromHex('-NaN'), NAN)
727 self.identical(fromHex('-nAN'), NAN)
728
729 # variations in input format
730 self.identical(fromHex('1'), 1.0)
731 self.identical(fromHex('+1'), 1.0)
732 self.identical(fromHex('1.'), 1.0)
733 self.identical(fromHex('1.0'), 1.0)
734 self.identical(fromHex('1.0p0'), 1.0)
735 self.identical(fromHex('01'), 1.0)
736 self.identical(fromHex('01.'), 1.0)
737 self.identical(fromHex('0x1'), 1.0)
738 self.identical(fromHex('0x1.'), 1.0)
739 self.identical(fromHex('0x1.0'), 1.0)
740 self.identical(fromHex('+0x1.0'), 1.0)
741 self.identical(fromHex('0x1p0'), 1.0)
742 self.identical(fromHex('0X1p0'), 1.0)
743 self.identical(fromHex('0X1P0'), 1.0)
744 self.identical(fromHex('0x1P0'), 1.0)
745 self.identical(fromHex('0x1.p0'), 1.0)
746 self.identical(fromHex('0x1.0p0'), 1.0)
747 self.identical(fromHex('0x.1p4'), 1.0)
748 self.identical(fromHex('0x.1p04'), 1.0)
749 self.identical(fromHex('0x.1p004'), 1.0)
750 self.identical(fromHex('0x1p+0'), 1.0)
751 self.identical(fromHex('0x1P-0'), 1.0)
752 self.identical(fromHex('+0x1p0'), 1.0)
753 self.identical(fromHex('0x01p0'), 1.0)
754 self.identical(fromHex('0x1p00'), 1.0)
755 self.identical(fromHex(' 0x1p0 '), 1.0)
756 self.identical(fromHex('\n 0x1p0'), 1.0)
757 self.identical(fromHex('0x1p0 \t'), 1.0)
758 self.identical(fromHex('0xap0'), 10.0)
759 self.identical(fromHex('0xAp0'), 10.0)
760 self.identical(fromHex('0xaP0'), 10.0)
761 self.identical(fromHex('0xAP0'), 10.0)
762 self.identical(fromHex('0xbep0'), 190.0)
763 self.identical(fromHex('0xBep0'), 190.0)
764 self.identical(fromHex('0xbEp0'), 190.0)
765 self.identical(fromHex('0XBE0P-4'), 190.0)
766 self.identical(fromHex('0xBEp0'), 190.0)
767 self.identical(fromHex('0xB.Ep4'), 190.0)
768 self.identical(fromHex('0x.BEp8'), 190.0)
769 self.identical(fromHex('0x.0BEp12'), 190.0)
770
771 # moving the point around
772 pi = fromHex('0x1.921fb54442d18p1')
773 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
774 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
775 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
776 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
777 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
778 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
779 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
780 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
781 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
782 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
783 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
784 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
785 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
786 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
787 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
788 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
789 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
790 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
791 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
792 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
793 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
794 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
795 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
796 # ...
797 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
798 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
799 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
800 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
801 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
802 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
803 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
804 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
805 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
806
807
808 # results that should overflow...
809 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
810 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
811 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
812 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
813 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
814 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
815 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
816 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
817 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
818 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
819 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
820 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
821 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
822 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
823 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
824 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
825 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
826 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
827 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
828
829 # ...and those that round to +-max float
830 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
831 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
832 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
833
834 # zeros
835 self.identical(fromHex('0x0p0'), 0.0)
836 self.identical(fromHex('0x0p1000'), 0.0)
837 self.identical(fromHex('-0x0p1023'), -0.0)
838 self.identical(fromHex('0X0p1024'), 0.0)
839 self.identical(fromHex('-0x0p1025'), -0.0)
840 self.identical(fromHex('0X0p2000'), 0.0)
841 self.identical(fromHex('0x0p123456789123456789'), 0.0)
842 self.identical(fromHex('-0X0p-0'), -0.0)
843 self.identical(fromHex('-0X0p-1000'), -0.0)
844 self.identical(fromHex('0x0p-1023'), 0.0)
845 self.identical(fromHex('-0X0p-1024'), -0.0)
846 self.identical(fromHex('-0x0p-1025'), -0.0)
847 self.identical(fromHex('-0x0p-1072'), -0.0)
848 self.identical(fromHex('0X0p-1073'), 0.0)
849 self.identical(fromHex('-0x0p-1074'), -0.0)
850 self.identical(fromHex('0x0p-1075'), 0.0)
851 self.identical(fromHex('0X0p-1076'), 0.0)
852 self.identical(fromHex('-0X0p-2000'), -0.0)
853 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
854
855 # values that should underflow to 0
856 self.identical(fromHex('0X1p-1075'), 0.0)
857 self.identical(fromHex('-0X1p-1075'), -0.0)
858 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
859 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
860 self.identical(fromHex('-0x1.1p-1075'), -TINY)
861 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
862
863 # check round-half-even is working correctly near 0 ...
864 self.identical(fromHex('0x1p-1076'), 0.0)
865 self.identical(fromHex('0X2p-1076'), 0.0)
866 self.identical(fromHex('0X3p-1076'), TINY)
867 self.identical(fromHex('0x4p-1076'), TINY)
868 self.identical(fromHex('0X5p-1076'), TINY)
869 self.identical(fromHex('0X6p-1076'), 2*TINY)
870 self.identical(fromHex('0x7p-1076'), 2*TINY)
871 self.identical(fromHex('0X8p-1076'), 2*TINY)
872 self.identical(fromHex('0X9p-1076'), 2*TINY)
873 self.identical(fromHex('0xap-1076'), 2*TINY)
874 self.identical(fromHex('0Xbp-1076'), 3*TINY)
875 self.identical(fromHex('0xcp-1076'), 3*TINY)
876 self.identical(fromHex('0Xdp-1076'), 3*TINY)
877 self.identical(fromHex('0Xep-1076'), 4*TINY)
878 self.identical(fromHex('0xfp-1076'), 4*TINY)
879 self.identical(fromHex('0x10p-1076'), 4*TINY)
880 self.identical(fromHex('-0x1p-1076'), -0.0)
881 self.identical(fromHex('-0X2p-1076'), -0.0)
882 self.identical(fromHex('-0x3p-1076'), -TINY)
883 self.identical(fromHex('-0X4p-1076'), -TINY)
884 self.identical(fromHex('-0x5p-1076'), -TINY)
885 self.identical(fromHex('-0x6p-1076'), -2*TINY)
886 self.identical(fromHex('-0X7p-1076'), -2*TINY)
887 self.identical(fromHex('-0X8p-1076'), -2*TINY)
888 self.identical(fromHex('-0X9p-1076'), -2*TINY)
889 self.identical(fromHex('-0Xap-1076'), -2*TINY)
890 self.identical(fromHex('-0xbp-1076'), -3*TINY)
891 self.identical(fromHex('-0xcp-1076'), -3*TINY)
892 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
893 self.identical(fromHex('-0xep-1076'), -4*TINY)
894 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
895 self.identical(fromHex('-0X10p-1076'), -4*TINY)
896
897 # ... and near MIN ...
898 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
899 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
900 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
901 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
902 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
903 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
904 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
905 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
906 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
907 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
908 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
909 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
910 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
911 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
912 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
913 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
914 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
915 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
916 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
917 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
918 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
919 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
920 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
921 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
922 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
923 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
924 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
925 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
926 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
927 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
928 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
929 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
930 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
931 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
932
933 # ... and near 1.0.
934 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
935 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
936 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
937 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
938 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
939 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
940 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
941 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
942 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
943 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
944 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
945 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
946 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
947 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
948 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
949 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
950 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
951 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
952 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
953 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
954 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
955 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
956 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
957 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
958 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
959 1.0)
960 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
961 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
962 1+EPS)
963 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
964 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
965 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
966 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
967 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
968 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
969 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
970 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
971 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
972 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
973 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
974 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
975 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
976 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
977 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
978 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
979 1.0+EPS)
980 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
981 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
982 1.0+2*EPS)
983 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
984 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
985 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
986 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
987 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
988 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
989 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
990 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
991
992 def test_roundtrip(self):
993 def roundtrip(x):
994 return fromHex(toHex(x))
995
996 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
997 self.identical(x, roundtrip(x))
998 self.identical(-x, roundtrip(-x))
999
1000 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1001 import random
1002 for i in range(10000):
1003 e = random.randrange(-1200, 1200)
1004 m = random.random()
1005 s = random.choice([1.0, -1.0])
1006 try:
1007 x = s*ldexp(m, e)
1008 except OverflowError:
1009 pass
1010 else:
1011 self.identical(x, fromHex(toHex(x)))
1012
Christian Heimes53876d92008-04-19 00:31:39 +00001013
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001014def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001015 support.run_unittest(
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00001016 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001017 FormatFunctionsTestCase,
1018 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +00001019 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +00001020 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001021 ReprTestCase,
Mark Dickinsone6a076d2009-04-18 11:48:33 +00001022 RoundTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001023 InfNanTest,
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001024 HexFloatTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +00001025 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001026
1027if __name__ == '__main__':
1028 test_main()