1 |
|
---|
2 | import unittest, struct
|
---|
3 | import os
|
---|
4 | from test import test_support
|
---|
5 | import math
|
---|
6 | from math import isinf, isnan, copysign, ldexp
|
---|
7 | import operator
|
---|
8 | import random
|
---|
9 | import fractions
|
---|
10 | import sys
|
---|
11 |
|
---|
12 | INF = float("inf")
|
---|
13 | NAN = float("nan")
|
---|
14 |
|
---|
15 | have_getformat = hasattr(float, "__getformat__")
|
---|
16 | requires_getformat = unittest.skipUnless(have_getformat,
|
---|
17 | "requires __getformat__")
|
---|
18 | requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__"),
|
---|
19 | "requires __setformat__")
|
---|
20 | # decorator for skipping tests on non-IEEE 754 platforms
|
---|
21 | requires_IEEE_754 = unittest.skipUnless(have_getformat and
|
---|
22 | float.__getformat__("double").startswith("IEEE"),
|
---|
23 | "test requires IEEE 754 doubles")
|
---|
24 |
|
---|
25 | #locate file with float format test values
|
---|
26 | test_dir = os.path.dirname(__file__) or os.curdir
|
---|
27 | format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
|
---|
28 |
|
---|
29 | class GeneralFloatCases(unittest.TestCase):
|
---|
30 |
|
---|
31 | def test_float(self):
|
---|
32 | self.assertEqual(float(3.14), 3.14)
|
---|
33 | self.assertEqual(float(314), 314.0)
|
---|
34 | self.assertEqual(float(314L), 314.0)
|
---|
35 | self.assertEqual(float(" 3.14 "), 3.14)
|
---|
36 | self.assertRaises(ValueError, float, " 0x3.1 ")
|
---|
37 | self.assertRaises(ValueError, float, " -0x3.p-1 ")
|
---|
38 | self.assertRaises(ValueError, float, " +0x3.p-1 ")
|
---|
39 | self.assertRaises(ValueError, float, "++3.14")
|
---|
40 | self.assertRaises(ValueError, float, "+-3.14")
|
---|
41 | self.assertRaises(ValueError, float, "-+3.14")
|
---|
42 | self.assertRaises(ValueError, float, "--3.14")
|
---|
43 | # check that we don't accept alternate exponent markers
|
---|
44 | self.assertRaises(ValueError, float, "-1.7d29")
|
---|
45 | self.assertRaises(ValueError, float, "3D-14")
|
---|
46 | if test_support.have_unicode:
|
---|
47 | self.assertEqual(float(unicode(" 3.14 ")), 3.14)
|
---|
48 | self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
|
---|
49 |
|
---|
50 | # extra long strings should no longer be a problem
|
---|
51 | # (in 2.6, long unicode inputs to float raised ValueError)
|
---|
52 | float('.' + '1'*1000)
|
---|
53 | float(unicode('.' + '1'*1000))
|
---|
54 |
|
---|
55 | def check_conversion_to_int(self, x):
|
---|
56 | """Check that int(x) has the correct value and type, for a float x."""
|
---|
57 | n = int(x)
|
---|
58 | if x >= 0.0:
|
---|
59 | # x >= 0 and n = int(x) ==> n <= x < n + 1
|
---|
60 | self.assertLessEqual(n, x)
|
---|
61 | self.assertLess(x, n + 1)
|
---|
62 | else:
|
---|
63 | # x < 0 and n = int(x) ==> n >= x > n - 1
|
---|
64 | self.assertGreaterEqual(n, x)
|
---|
65 | self.assertGreater(x, n - 1)
|
---|
66 |
|
---|
67 | # Result should be an int if within range, else a long.
|
---|
68 | if -sys.maxint-1 <= n <= sys.maxint:
|
---|
69 | self.assertEqual(type(n), int)
|
---|
70 | else:
|
---|
71 | self.assertEqual(type(n), long)
|
---|
72 |
|
---|
73 | # Double check.
|
---|
74 | self.assertEqual(type(int(n)), type(n))
|
---|
75 |
|
---|
76 | def test_conversion_to_int(self):
|
---|
77 | # Check that floats within the range of an int convert to type
|
---|
78 | # int, not long. (issue #11144.)
|
---|
79 | boundary = float(sys.maxint + 1)
|
---|
80 | epsilon = 2**-sys.float_info.mant_dig * boundary
|
---|
81 |
|
---|
82 | # These 2 floats are either side of the positive int/long boundary on
|
---|
83 | # both 32-bit and 64-bit systems.
|
---|
84 | self.check_conversion_to_int(boundary - epsilon)
|
---|
85 | self.check_conversion_to_int(boundary)
|
---|
86 |
|
---|
87 | # These floats are either side of the negative long/int boundary on
|
---|
88 | # 64-bit systems...
|
---|
89 | self.check_conversion_to_int(-boundary - 2*epsilon)
|
---|
90 | self.check_conversion_to_int(-boundary)
|
---|
91 |
|
---|
92 | # ... and these ones are either side of the negative long/int
|
---|
93 | # boundary on 32-bit systems.
|
---|
94 | self.check_conversion_to_int(-boundary - 1.0)
|
---|
95 | self.check_conversion_to_int(-boundary - 1.0 + 2*epsilon)
|
---|
96 |
|
---|
97 | @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
|
---|
98 | def test_float_with_comma(self):
|
---|
99 | # set locale to something that doesn't use '.' for the decimal point
|
---|
100 | # float must not accept the locale specific decimal point but
|
---|
101 | # it still has to accept the normal python syntax
|
---|
102 | import locale
|
---|
103 | if not locale.localeconv()['decimal_point'] == ',':
|
---|
104 | return
|
---|
105 |
|
---|
106 | self.assertEqual(float(" 3.14 "), 3.14)
|
---|
107 | self.assertEqual(float("+3.14 "), 3.14)
|
---|
108 | self.assertEqual(float("-3.14 "), -3.14)
|
---|
109 | self.assertEqual(float(".14 "), .14)
|
---|
110 | self.assertEqual(float("3. "), 3.0)
|
---|
111 | self.assertEqual(float("3.e3 "), 3000.0)
|
---|
112 | self.assertEqual(float("3.2e3 "), 3200.0)
|
---|
113 | self.assertEqual(float("2.5e-1 "), 0.25)
|
---|
114 | self.assertEqual(float("5e-1"), 0.5)
|
---|
115 | self.assertRaises(ValueError, float, " 3,14 ")
|
---|
116 | self.assertRaises(ValueError, float, " +3,14 ")
|
---|
117 | self.assertRaises(ValueError, float, " -3,14 ")
|
---|
118 | self.assertRaises(ValueError, float, " 0x3.1 ")
|
---|
119 | self.assertRaises(ValueError, float, " -0x3.p-1 ")
|
---|
120 | self.assertRaises(ValueError, float, " +0x3.p-1 ")
|
---|
121 | self.assertEqual(float(" 25.e-1 "), 2.5)
|
---|
122 | self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
|
---|
123 |
|
---|
124 | def test_floatconversion(self):
|
---|
125 | # Make sure that calls to __float__() work properly
|
---|
126 | class Foo0:
|
---|
127 | def __float__(self):
|
---|
128 | return 42.
|
---|
129 |
|
---|
130 | class Foo1(object):
|
---|
131 | def __float__(self):
|
---|
132 | return 42.
|
---|
133 |
|
---|
134 | class Foo2(float):
|
---|
135 | def __float__(self):
|
---|
136 | return 42.
|
---|
137 |
|
---|
138 | class Foo3(float):
|
---|
139 | def __new__(cls, value=0.):
|
---|
140 | return float.__new__(cls, 2*value)
|
---|
141 |
|
---|
142 | def __float__(self):
|
---|
143 | return self
|
---|
144 |
|
---|
145 | class Foo4(float):
|
---|
146 | def __float__(self):
|
---|
147 | return 42
|
---|
148 |
|
---|
149 | # Issue 5759: __float__ not called on str subclasses (though it is on
|
---|
150 | # unicode subclasses).
|
---|
151 | class FooStr(str):
|
---|
152 | def __float__(self):
|
---|
153 | return float(str(self)) + 1
|
---|
154 |
|
---|
155 | class FooUnicode(unicode):
|
---|
156 | def __float__(self):
|
---|
157 | return float(unicode(self)) + 1
|
---|
158 |
|
---|
159 | self.assertAlmostEqual(float(Foo0()), 42.)
|
---|
160 | self.assertAlmostEqual(float(Foo1()), 42.)
|
---|
161 | self.assertAlmostEqual(float(Foo2()), 42.)
|
---|
162 | self.assertAlmostEqual(float(Foo3(21)), 42.)
|
---|
163 | self.assertRaises(TypeError, float, Foo4(42))
|
---|
164 | self.assertAlmostEqual(float(FooUnicode('8')), 9.)
|
---|
165 | self.assertAlmostEqual(float(FooStr('8')), 9.)
|
---|
166 |
|
---|
167 | def test_is_integer(self):
|
---|
168 | self.assertFalse((1.1).is_integer())
|
---|
169 | self.assertTrue((1.).is_integer())
|
---|
170 | self.assertFalse(float("nan").is_integer())
|
---|
171 | self.assertFalse(float("inf").is_integer())
|
---|
172 |
|
---|
173 | def test_floatasratio(self):
|
---|
174 | for f, ratio in [
|
---|
175 | (0.875, (7, 8)),
|
---|
176 | (-0.875, (-7, 8)),
|
---|
177 | (0.0, (0, 1)),
|
---|
178 | (11.5, (23, 2)),
|
---|
179 | ]:
|
---|
180 | self.assertEqual(f.as_integer_ratio(), ratio)
|
---|
181 |
|
---|
182 | for i in range(10000):
|
---|
183 | f = random.random()
|
---|
184 | f *= 10 ** random.randint(-100, 100)
|
---|
185 | n, d = f.as_integer_ratio()
|
---|
186 | self.assertEqual(float(n).__truediv__(d), f)
|
---|
187 |
|
---|
188 | R = fractions.Fraction
|
---|
189 | self.assertEqual(R(0, 1),
|
---|
190 | R(*float(0.0).as_integer_ratio()))
|
---|
191 | self.assertEqual(R(5, 2),
|
---|
192 | R(*float(2.5).as_integer_ratio()))
|
---|
193 | self.assertEqual(R(1, 2),
|
---|
194 | R(*float(0.5).as_integer_ratio()))
|
---|
195 | self.assertEqual(R(4728779608739021, 2251799813685248),
|
---|
196 | R(*float(2.1).as_integer_ratio()))
|
---|
197 | self.assertEqual(R(-4728779608739021, 2251799813685248),
|
---|
198 | R(*float(-2.1).as_integer_ratio()))
|
---|
199 | self.assertEqual(R(-2100, 1),
|
---|
200 | R(*float(-2100.0).as_integer_ratio()))
|
---|
201 |
|
---|
202 | self.assertRaises(OverflowError, float('inf').as_integer_ratio)
|
---|
203 | self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
|
---|
204 | self.assertRaises(ValueError, float('nan').as_integer_ratio)
|
---|
205 |
|
---|
206 | def assertEqualAndEqualSign(self, a, b):
|
---|
207 | # fail unless a == b and a and b have the same sign bit;
|
---|
208 | # the only difference from assertEqual is that this test
|
---|
209 | # distinguishes -0.0 and 0.0.
|
---|
210 | self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
|
---|
211 |
|
---|
212 | @requires_IEEE_754
|
---|
213 | def test_float_mod(self):
|
---|
214 | # Check behaviour of % operator for IEEE 754 special cases.
|
---|
215 | # In particular, check signs of zeros.
|
---|
216 | mod = operator.mod
|
---|
217 |
|
---|
218 | self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0)
|
---|
219 | self.assertEqualAndEqualSign(mod(-1e-100, 1.0), 1.0)
|
---|
220 | self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0)
|
---|
221 | self.assertEqualAndEqualSign(mod(0.0, 1.0), 0.0)
|
---|
222 | self.assertEqualAndEqualSign(mod(1e-100, 1.0), 1e-100)
|
---|
223 | self.assertEqualAndEqualSign(mod(1.0, 1.0), 0.0)
|
---|
224 |
|
---|
225 | self.assertEqualAndEqualSign(mod(-1.0, -1.0), -0.0)
|
---|
226 | self.assertEqualAndEqualSign(mod(-1e-100, -1.0), -1e-100)
|
---|
227 | self.assertEqualAndEqualSign(mod(-0.0, -1.0), -0.0)
|
---|
228 | self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0)
|
---|
229 | self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0)
|
---|
230 | self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0)
|
---|
231 |
|
---|
232 | @requires_IEEE_754
|
---|
233 | def test_float_pow(self):
|
---|
234 | # test builtin pow and ** operator for IEEE 754 special cases.
|
---|
235 | # Special cases taken from section F.9.4.4 of the C99 specification
|
---|
236 |
|
---|
237 | for pow_op in pow, operator.pow:
|
---|
238 | # x**NAN is NAN for any x except 1
|
---|
239 | self.assertTrue(isnan(pow_op(-INF, NAN)))
|
---|
240 | self.assertTrue(isnan(pow_op(-2.0, NAN)))
|
---|
241 | self.assertTrue(isnan(pow_op(-1.0, NAN)))
|
---|
242 | self.assertTrue(isnan(pow_op(-0.5, NAN)))
|
---|
243 | self.assertTrue(isnan(pow_op(-0.0, NAN)))
|
---|
244 | self.assertTrue(isnan(pow_op(0.0, NAN)))
|
---|
245 | self.assertTrue(isnan(pow_op(0.5, NAN)))
|
---|
246 | self.assertTrue(isnan(pow_op(2.0, NAN)))
|
---|
247 | self.assertTrue(isnan(pow_op(INF, NAN)))
|
---|
248 | self.assertTrue(isnan(pow_op(NAN, NAN)))
|
---|
249 |
|
---|
250 | # NAN**y is NAN for any y except +-0
|
---|
251 | self.assertTrue(isnan(pow_op(NAN, -INF)))
|
---|
252 | self.assertTrue(isnan(pow_op(NAN, -2.0)))
|
---|
253 | self.assertTrue(isnan(pow_op(NAN, -1.0)))
|
---|
254 | self.assertTrue(isnan(pow_op(NAN, -0.5)))
|
---|
255 | self.assertTrue(isnan(pow_op(NAN, 0.5)))
|
---|
256 | self.assertTrue(isnan(pow_op(NAN, 1.0)))
|
---|
257 | self.assertTrue(isnan(pow_op(NAN, 2.0)))
|
---|
258 | self.assertTrue(isnan(pow_op(NAN, INF)))
|
---|
259 |
|
---|
260 | # (+-0)**y raises ZeroDivisionError for y a negative odd integer
|
---|
261 | self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
|
---|
262 | self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
|
---|
263 |
|
---|
264 | # (+-0)**y raises ZeroDivisionError for y finite and negative
|
---|
265 | # but not an odd integer
|
---|
266 | self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
|
---|
267 | self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
|
---|
268 | self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
|
---|
269 | self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
|
---|
270 |
|
---|
271 | # (+-0)**y is +-0 for y a positive odd integer
|
---|
272 | self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
|
---|
273 | self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
|
---|
274 |
|
---|
275 | # (+-0)**y is 0 for y finite and positive but not an odd integer
|
---|
276 | self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
|
---|
277 | self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
|
---|
278 | self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
|
---|
279 | self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
|
---|
280 |
|
---|
281 | # (-1)**+-inf is 1
|
---|
282 | self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
|
---|
283 | self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
|
---|
284 |
|
---|
285 | # 1**y is 1 for any y, even if y is an infinity or nan
|
---|
286 | self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
|
---|
287 | self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
|
---|
288 | self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
|
---|
289 | self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
|
---|
290 | self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
|
---|
291 | self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
|
---|
292 | self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
|
---|
293 | self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
|
---|
294 | self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
|
---|
295 | self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
|
---|
296 | self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
|
---|
297 |
|
---|
298 | # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
|
---|
299 | self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
|
---|
300 | self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
|
---|
301 | self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
|
---|
302 | self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
|
---|
303 | self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
|
---|
304 | self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
|
---|
305 | self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
|
---|
306 | self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
|
---|
307 | self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
|
---|
308 | self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
|
---|
309 | self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
|
---|
310 | self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
|
---|
311 | self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
|
---|
312 | self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
|
---|
313 | self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
|
---|
314 | self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
|
---|
315 | self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
|
---|
316 | self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
|
---|
317 | self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
|
---|
318 | self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
|
---|
319 | self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
|
---|
320 | self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
|
---|
321 |
|
---|
322 | # x**y raises ValueError for finite negative x and non-integral y
|
---|
323 | self.assertRaises(ValueError, pow_op, -2.0, -0.5)
|
---|
324 | self.assertRaises(ValueError, pow_op, -2.0, 0.5)
|
---|
325 | self.assertRaises(ValueError, pow_op, -1.0, -0.5)
|
---|
326 | self.assertRaises(ValueError, pow_op, -1.0, 0.5)
|
---|
327 | self.assertRaises(ValueError, pow_op, -0.5, -0.5)
|
---|
328 | self.assertRaises(ValueError, pow_op, -0.5, 0.5)
|
---|
329 |
|
---|
330 | # x**-INF is INF for abs(x) < 1
|
---|
331 | self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
|
---|
332 | self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
|
---|
333 | self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
|
---|
334 | self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
|
---|
335 |
|
---|
336 | # x**-INF is 0 for abs(x) > 1
|
---|
337 | self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
|
---|
338 | self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
|
---|
339 | self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
|
---|
340 | self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
|
---|
341 |
|
---|
342 | # x**INF is 0 for abs(x) < 1
|
---|
343 | self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
|
---|
344 | self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
|
---|
345 | self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
|
---|
346 | self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
|
---|
347 |
|
---|
348 | # x**INF is INF for abs(x) > 1
|
---|
349 | self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
|
---|
350 | self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
|
---|
351 | self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
|
---|
352 | self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
|
---|
353 |
|
---|
354 | # (-INF)**y is -0.0 for y a negative odd integer
|
---|
355 | self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
|
---|
356 |
|
---|
357 | # (-INF)**y is 0.0 for y negative but not an odd integer
|
---|
358 | self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
|
---|
359 | self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
|
---|
360 |
|
---|
361 | # (-INF)**y is -INF for y a positive odd integer
|
---|
362 | self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
|
---|
363 |
|
---|
364 | # (-INF)**y is INF for y positive but not an odd integer
|
---|
365 | self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
|
---|
366 | self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
|
---|
367 |
|
---|
368 | # INF**y is INF for y positive
|
---|
369 | self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
|
---|
370 | self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
|
---|
371 | self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
|
---|
372 |
|
---|
373 | # INF**y is 0.0 for y negative
|
---|
374 | self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
|
---|
375 | self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
|
---|
376 | self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
|
---|
377 |
|
---|
378 | # basic checks not covered by the special cases above
|
---|
379 | self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
|
---|
380 | self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
|
---|
381 | self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
|
---|
382 | self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
|
---|
383 | self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
|
---|
384 | self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
|
---|
385 | self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
|
---|
386 | self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
|
---|
387 | self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
|
---|
388 | self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
|
---|
389 | self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
|
---|
390 | self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
|
---|
391 | self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
|
---|
392 | self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
|
---|
393 | self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
|
---|
394 | self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
|
---|
395 | self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
|
---|
396 | self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
|
---|
397 |
|
---|
398 | # 1 ** large and -1 ** large; some libms apparently
|
---|
399 | # have problems with these
|
---|
400 | self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
|
---|
401 | self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
|
---|
402 | self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
|
---|
403 | self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
|
---|
404 |
|
---|
405 | # check sign for results that underflow to 0
|
---|
406 | self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
|
---|
407 | self.assertRaises(ValueError, pow_op, -2.0, -2000.5)
|
---|
408 | self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
|
---|
409 | self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
|
---|
410 | self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
|
---|
411 | self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
|
---|
412 | self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
|
---|
413 | self.assertRaises(ValueError, pow_op, -0.5, 2000.5)
|
---|
414 | self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
|
---|
415 | self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
|
---|
416 | self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
|
---|
417 | self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
|
---|
418 |
|
---|
419 | # check we don't raise an exception for subnormal results,
|
---|
420 | # and validate signs. Tests currently disabled, since
|
---|
421 | # they fail on systems where a subnormal result from pow
|
---|
422 | # is flushed to zero (e.g. Debian/ia64.)
|
---|
423 | #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
|
---|
424 | #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
|
---|
425 | #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
|
---|
426 | #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
|
---|
427 | #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
|
---|
428 | #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
|
---|
429 | #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
|
---|
430 | #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
|
---|
431 |
|
---|
432 |
|
---|
433 | @requires_setformat
|
---|
434 | class FormatFunctionsTestCase(unittest.TestCase):
|
---|
435 |
|
---|
436 | def setUp(self):
|
---|
437 | self.save_formats = {'double':float.__getformat__('double'),
|
---|
438 | 'float':float.__getformat__('float')}
|
---|
439 |
|
---|
440 | def tearDown(self):
|
---|
441 | float.__setformat__('double', self.save_formats['double'])
|
---|
442 | float.__setformat__('float', self.save_formats['float'])
|
---|
443 |
|
---|
444 | def test_getformat(self):
|
---|
445 | self.assertIn(float.__getformat__('double'),
|
---|
446 | ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
|
---|
447 | self.assertIn(float.__getformat__('float'),
|
---|
448 | ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
|
---|
449 | self.assertRaises(ValueError, float.__getformat__, 'chicken')
|
---|
450 | self.assertRaises(TypeError, float.__getformat__, 1)
|
---|
451 |
|
---|
452 | def test_setformat(self):
|
---|
453 | for t in 'double', 'float':
|
---|
454 | float.__setformat__(t, 'unknown')
|
---|
455 | if self.save_formats[t] == 'IEEE, big-endian':
|
---|
456 | self.assertRaises(ValueError, float.__setformat__,
|
---|
457 | t, 'IEEE, little-endian')
|
---|
458 | elif self.save_formats[t] == 'IEEE, little-endian':
|
---|
459 | self.assertRaises(ValueError, float.__setformat__,
|
---|
460 | t, 'IEEE, big-endian')
|
---|
461 | else:
|
---|
462 | self.assertRaises(ValueError, float.__setformat__,
|
---|
463 | t, 'IEEE, big-endian')
|
---|
464 | self.assertRaises(ValueError, float.__setformat__,
|
---|
465 | t, 'IEEE, little-endian')
|
---|
466 | self.assertRaises(ValueError, float.__setformat__,
|
---|
467 | t, 'chicken')
|
---|
468 | self.assertRaises(ValueError, float.__setformat__,
|
---|
469 | 'chicken', 'unknown')
|
---|
470 |
|
---|
471 | BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
|
---|
472 | LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
|
---|
473 | BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
|
---|
474 | LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
|
---|
475 |
|
---|
476 | BE_FLOAT_INF = '\x7f\x80\x00\x00'
|
---|
477 | LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
|
---|
478 | BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
|
---|
479 | LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
|
---|
480 |
|
---|
481 | # on non-IEEE platforms, attempting to unpack a bit pattern
|
---|
482 | # representing an infinity or a NaN should raise an exception.
|
---|
483 |
|
---|
484 | @requires_setformat
|
---|
485 | class UnknownFormatTestCase(unittest.TestCase):
|
---|
486 | def setUp(self):
|
---|
487 | self.save_formats = {'double':float.__getformat__('double'),
|
---|
488 | 'float':float.__getformat__('float')}
|
---|
489 | float.__setformat__('double', 'unknown')
|
---|
490 | float.__setformat__('float', 'unknown')
|
---|
491 |
|
---|
492 | def tearDown(self):
|
---|
493 | float.__setformat__('double', self.save_formats['double'])
|
---|
494 | float.__setformat__('float', self.save_formats['float'])
|
---|
495 |
|
---|
496 | def test_double_specials_dont_unpack(self):
|
---|
497 | for fmt, data in [('>d', BE_DOUBLE_INF),
|
---|
498 | ('>d', BE_DOUBLE_NAN),
|
---|
499 | ('<d', LE_DOUBLE_INF),
|
---|
500 | ('<d', LE_DOUBLE_NAN)]:
|
---|
501 | self.assertRaises(ValueError, struct.unpack, fmt, data)
|
---|
502 |
|
---|
503 | def test_float_specials_dont_unpack(self):
|
---|
504 | for fmt, data in [('>f', BE_FLOAT_INF),
|
---|
505 | ('>f', BE_FLOAT_NAN),
|
---|
506 | ('<f', LE_FLOAT_INF),
|
---|
507 | ('<f', LE_FLOAT_NAN)]:
|
---|
508 | self.assertRaises(ValueError, struct.unpack, fmt, data)
|
---|
509 |
|
---|
510 |
|
---|
511 | # on an IEEE platform, all we guarantee is that bit patterns
|
---|
512 | # representing infinities or NaNs do not raise an exception; all else
|
---|
513 | # is accident (today).
|
---|
514 | # let's also try to guarantee that -0.0 and 0.0 don't get confused.
|
---|
515 |
|
---|
516 | class IEEEFormatTestCase(unittest.TestCase):
|
---|
517 |
|
---|
518 | @requires_IEEE_754
|
---|
519 | def test_double_specials_do_unpack(self):
|
---|
520 | for fmt, data in [('>d', BE_DOUBLE_INF),
|
---|
521 | ('>d', BE_DOUBLE_NAN),
|
---|
522 | ('<d', LE_DOUBLE_INF),
|
---|
523 | ('<d', LE_DOUBLE_NAN)]:
|
---|
524 | struct.unpack(fmt, data)
|
---|
525 |
|
---|
526 | @requires_IEEE_754
|
---|
527 | def test_float_specials_do_unpack(self):
|
---|
528 | for fmt, data in [('>f', BE_FLOAT_INF),
|
---|
529 | ('>f', BE_FLOAT_NAN),
|
---|
530 | ('<f', LE_FLOAT_INF),
|
---|
531 | ('<f', LE_FLOAT_NAN)]:
|
---|
532 | struct.unpack(fmt, data)
|
---|
533 |
|
---|
534 | @requires_IEEE_754
|
---|
535 | def test_negative_zero(self):
|
---|
536 | def pos_pos():
|
---|
537 | return 0.0, math.atan2(0.0, -1)
|
---|
538 | def pos_neg():
|
---|
539 | return 0.0, math.atan2(-0.0, -1)
|
---|
540 | def neg_pos():
|
---|
541 | return -0.0, math.atan2(0.0, -1)
|
---|
542 | def neg_neg():
|
---|
543 | return -0.0, math.atan2(-0.0, -1)
|
---|
544 | self.assertEqual(pos_pos(), neg_pos())
|
---|
545 | self.assertEqual(pos_neg(), neg_neg())
|
---|
546 |
|
---|
547 | @requires_IEEE_754
|
---|
548 | def test_underflow_sign(self):
|
---|
549 | # check that -1e-1000 gives -0.0, not 0.0
|
---|
550 | self.assertEqual(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
|
---|
551 | self.assertEqual(math.atan2(float('-1e-1000'), -1),
|
---|
552 | math.atan2(-0.0, -1))
|
---|
553 |
|
---|
554 | def test_format(self):
|
---|
555 | # these should be rewritten to use both format(x, spec) and
|
---|
556 | # x.__format__(spec)
|
---|
557 |
|
---|
558 | self.assertEqual(format(0.0, 'f'), '0.000000')
|
---|
559 |
|
---|
560 | # the default is 'g', except for empty format spec
|
---|
561 | self.assertEqual(format(0.0, ''), '0.0')
|
---|
562 | self.assertEqual(format(0.01, ''), '0.01')
|
---|
563 | self.assertEqual(format(0.01, 'g'), '0.01')
|
---|
564 |
|
---|
565 | # empty presentation type should format in the same way as str
|
---|
566 | # (issue 5920)
|
---|
567 | x = 100/7.
|
---|
568 | self.assertEqual(format(x, ''), str(x))
|
---|
569 | self.assertEqual(format(x, '-'), str(x))
|
---|
570 | self.assertEqual(format(x, '>'), str(x))
|
---|
571 | self.assertEqual(format(x, '2'), str(x))
|
---|
572 |
|
---|
573 | self.assertEqual(format(1.0, 'f'), '1.000000')
|
---|
574 |
|
---|
575 | self.assertEqual(format(-1.0, 'f'), '-1.000000')
|
---|
576 |
|
---|
577 | self.assertEqual(format( 1.0, ' f'), ' 1.000000')
|
---|
578 | self.assertEqual(format(-1.0, ' f'), '-1.000000')
|
---|
579 | self.assertEqual(format( 1.0, '+f'), '+1.000000')
|
---|
580 | self.assertEqual(format(-1.0, '+f'), '-1.000000')
|
---|
581 |
|
---|
582 | # % formatting
|
---|
583 | self.assertEqual(format(-1.0, '%'), '-100.000000%')
|
---|
584 |
|
---|
585 | # conversion to string should fail
|
---|
586 | self.assertRaises(ValueError, format, 3.0, "s")
|
---|
587 |
|
---|
588 | # other format specifiers shouldn't work on floats,
|
---|
589 | # in particular int specifiers
|
---|
590 | for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
|
---|
591 | [chr(x) for x in range(ord('A'), ord('Z')+1)]):
|
---|
592 | if not format_spec in 'eEfFgGn%':
|
---|
593 | self.assertRaises(ValueError, format, 0.0, format_spec)
|
---|
594 | self.assertRaises(ValueError, format, 1.0, format_spec)
|
---|
595 | self.assertRaises(ValueError, format, -1.0, format_spec)
|
---|
596 | self.assertRaises(ValueError, format, 1e100, format_spec)
|
---|
597 | self.assertRaises(ValueError, format, -1e100, format_spec)
|
---|
598 | self.assertRaises(ValueError, format, 1e-100, format_spec)
|
---|
599 | self.assertRaises(ValueError, format, -1e-100, format_spec)
|
---|
600 |
|
---|
601 | # issue 3382: 'f' and 'F' with inf's and nan's
|
---|
602 | self.assertEqual('{0:f}'.format(INF), 'inf')
|
---|
603 | self.assertEqual('{0:F}'.format(INF), 'INF')
|
---|
604 | self.assertEqual('{0:f}'.format(-INF), '-inf')
|
---|
605 | self.assertEqual('{0:F}'.format(-INF), '-INF')
|
---|
606 | self.assertEqual('{0:f}'.format(NAN), 'nan')
|
---|
607 | self.assertEqual('{0:F}'.format(NAN), 'NAN')
|
---|
608 |
|
---|
609 | @requires_IEEE_754
|
---|
610 | def test_format_testfile(self):
|
---|
611 | with open(format_testfile) as testfile:
|
---|
612 | for line in open(format_testfile):
|
---|
613 | if line.startswith('--'):
|
---|
614 | continue
|
---|
615 | line = line.strip()
|
---|
616 | if not line:
|
---|
617 | continue
|
---|
618 |
|
---|
619 | lhs, rhs = map(str.strip, line.split('->'))
|
---|
620 | fmt, arg = lhs.split()
|
---|
621 | arg = float(arg)
|
---|
622 | self.assertEqual(fmt % arg, rhs)
|
---|
623 | if not math.isnan(arg) and copysign(1.0, arg) > 0.0:
|
---|
624 | self.assertEqual(fmt % -arg, '-' + rhs)
|
---|
625 |
|
---|
626 | def test_issue5864(self):
|
---|
627 | self.assertEqual(format(123.456, '.4'), '123.5')
|
---|
628 | self.assertEqual(format(1234.56, '.4'), '1.235e+03')
|
---|
629 | self.assertEqual(format(12345.6, '.4'), '1.235e+04')
|
---|
630 |
|
---|
631 | class ReprTestCase(unittest.TestCase):
|
---|
632 | def test_repr(self):
|
---|
633 | floats_file = open(os.path.join(os.path.split(__file__)[0],
|
---|
634 | 'floating_points.txt'))
|
---|
635 | for line in floats_file:
|
---|
636 | line = line.strip()
|
---|
637 | if not line or line.startswith('#'):
|
---|
638 | continue
|
---|
639 | v = eval(line)
|
---|
640 | self.assertEqual(v, eval(repr(v)))
|
---|
641 | floats_file.close()
|
---|
642 |
|
---|
643 | @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
|
---|
644 | "applies only when using short float repr style")
|
---|
645 | def test_short_repr(self):
|
---|
646 | # test short float repr introduced in Python 3.1. One aspect
|
---|
647 | # of this repr is that we get some degree of str -> float ->
|
---|
648 | # str roundtripping. In particular, for any numeric string
|
---|
649 | # containing 15 or fewer significant digits, those exact same
|
---|
650 | # digits (modulo trailing zeros) should appear in the output.
|
---|
651 | # No more repr(0.03) -> "0.029999999999999999"!
|
---|
652 |
|
---|
653 | test_strings = [
|
---|
654 | # output always includes *either* a decimal point and at
|
---|
655 | # least one digit after that point, or an exponent.
|
---|
656 | '0.0',
|
---|
657 | '1.0',
|
---|
658 | '0.01',
|
---|
659 | '0.02',
|
---|
660 | '0.03',
|
---|
661 | '0.04',
|
---|
662 | '0.05',
|
---|
663 | '1.23456789',
|
---|
664 | '10.0',
|
---|
665 | '100.0',
|
---|
666 | # values >= 1e16 get an exponent...
|
---|
667 | '1000000000000000.0',
|
---|
668 | '9999999999999990.0',
|
---|
669 | '1e+16',
|
---|
670 | '1e+17',
|
---|
671 | # ... and so do values < 1e-4
|
---|
672 | '0.001',
|
---|
673 | '0.001001',
|
---|
674 | '0.00010000000000001',
|
---|
675 | '0.0001',
|
---|
676 | '9.999999999999e-05',
|
---|
677 | '1e-05',
|
---|
678 | # values designed to provoke failure if the FPU rounding
|
---|
679 | # precision isn't set correctly
|
---|
680 | '8.72293771110361e+25',
|
---|
681 | '7.47005307342313e+26',
|
---|
682 | '2.86438000439698e+28',
|
---|
683 | '8.89142905246179e+28',
|
---|
684 | '3.08578087079232e+35',
|
---|
685 | ]
|
---|
686 |
|
---|
687 | for s in test_strings:
|
---|
688 | negs = '-'+s
|
---|
689 | self.assertEqual(s, repr(float(s)))
|
---|
690 | self.assertEqual(negs, repr(float(negs)))
|
---|
691 |
|
---|
692 |
|
---|
693 | @requires_IEEE_754
|
---|
694 | class RoundTestCase(unittest.TestCase):
|
---|
695 | def test_second_argument_type(self):
|
---|
696 | # any type with an __index__ method should be permitted as
|
---|
697 | # a second argument
|
---|
698 | self.assertAlmostEqual(round(12.34, True), 12.3)
|
---|
699 |
|
---|
700 | class MyIndex(object):
|
---|
701 | def __index__(self): return 4
|
---|
702 | self.assertAlmostEqual(round(-0.123456, MyIndex()), -0.1235)
|
---|
703 | # but floats should be illegal
|
---|
704 | self.assertRaises(TypeError, round, 3.14159, 2.0)
|
---|
705 |
|
---|
706 | def test_inf_nan(self):
|
---|
707 | # rounding an infinity or nan returns the same number;
|
---|
708 | # (in py3k, rounding an infinity or nan raises an error,
|
---|
709 | # since the result can't be represented as a long).
|
---|
710 | self.assertEqual(round(INF), INF)
|
---|
711 | self.assertEqual(round(-INF), -INF)
|
---|
712 | self.assertTrue(math.isnan(round(NAN)))
|
---|
713 | for n in range(-5, 5):
|
---|
714 | self.assertEqual(round(INF, n), INF)
|
---|
715 | self.assertEqual(round(-INF, n), -INF)
|
---|
716 | self.assertTrue(math.isnan(round(NAN, n)))
|
---|
717 |
|
---|
718 | self.assertRaises(TypeError, round, INF, 0.0)
|
---|
719 | self.assertRaises(TypeError, round, -INF, 1.0)
|
---|
720 | self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
|
---|
721 | self.assertRaises(TypeError, round, -0.0, 1j)
|
---|
722 |
|
---|
723 | def test_large_n(self):
|
---|
724 | for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
|
---|
725 | self.assertEqual(round(123.456, n), 123.456)
|
---|
726 | self.assertEqual(round(-123.456, n), -123.456)
|
---|
727 | self.assertEqual(round(1e300, n), 1e300)
|
---|
728 | self.assertEqual(round(1e-320, n), 1e-320)
|
---|
729 | self.assertEqual(round(1e150, 300), 1e150)
|
---|
730 | self.assertEqual(round(1e300, 307), 1e300)
|
---|
731 | self.assertEqual(round(-3.1415, 308), -3.1415)
|
---|
732 | self.assertEqual(round(1e150, 309), 1e150)
|
---|
733 | self.assertEqual(round(1.4e-315, 315), 1e-315)
|
---|
734 |
|
---|
735 | def test_small_n(self):
|
---|
736 | for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
|
---|
737 | self.assertEqual(round(123.456, n), 0.0)
|
---|
738 | self.assertEqual(round(-123.456, n), -0.0)
|
---|
739 | self.assertEqual(round(1e300, n), 0.0)
|
---|
740 | self.assertEqual(round(1e-320, n), 0.0)
|
---|
741 |
|
---|
742 | def test_overflow(self):
|
---|
743 | self.assertRaises(OverflowError, round, 1.6e308, -308)
|
---|
744 | self.assertRaises(OverflowError, round, -1.7e308, -308)
|
---|
745 |
|
---|
746 | @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
|
---|
747 | "test applies only when using short float repr style")
|
---|
748 | def test_previous_round_bugs(self):
|
---|
749 | # particular cases that have occurred in bug reports
|
---|
750 | self.assertEqual(round(562949953421312.5, 1),
|
---|
751 | 562949953421312.5)
|
---|
752 | self.assertEqual(round(56294995342131.5, 3),
|
---|
753 | 56294995342131.5)
|
---|
754 |
|
---|
755 | @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
|
---|
756 | "test applies only when using short float repr style")
|
---|
757 | def test_halfway_cases(self):
|
---|
758 | # Halfway cases need special attention, since the current
|
---|
759 | # implementation has to deal with them specially. Note that
|
---|
760 | # 2.x rounds halfway values up (i.e., away from zero) while
|
---|
761 | # 3.x does round-half-to-even.
|
---|
762 | self.assertAlmostEqual(round(0.125, 2), 0.13)
|
---|
763 | self.assertAlmostEqual(round(0.375, 2), 0.38)
|
---|
764 | self.assertAlmostEqual(round(0.625, 2), 0.63)
|
---|
765 | self.assertAlmostEqual(round(0.875, 2), 0.88)
|
---|
766 | self.assertAlmostEqual(round(-0.125, 2), -0.13)
|
---|
767 | self.assertAlmostEqual(round(-0.375, 2), -0.38)
|
---|
768 | self.assertAlmostEqual(round(-0.625, 2), -0.63)
|
---|
769 | self.assertAlmostEqual(round(-0.875, 2), -0.88)
|
---|
770 |
|
---|
771 | self.assertAlmostEqual(round(0.25, 1), 0.3)
|
---|
772 | self.assertAlmostEqual(round(0.75, 1), 0.8)
|
---|
773 | self.assertAlmostEqual(round(-0.25, 1), -0.3)
|
---|
774 | self.assertAlmostEqual(round(-0.75, 1), -0.8)
|
---|
775 |
|
---|
776 | self.assertEqual(round(-6.5, 0), -7.0)
|
---|
777 | self.assertEqual(round(-5.5, 0), -6.0)
|
---|
778 | self.assertEqual(round(-1.5, 0), -2.0)
|
---|
779 | self.assertEqual(round(-0.5, 0), -1.0)
|
---|
780 | self.assertEqual(round(0.5, 0), 1.0)
|
---|
781 | self.assertEqual(round(1.5, 0), 2.0)
|
---|
782 | self.assertEqual(round(2.5, 0), 3.0)
|
---|
783 | self.assertEqual(round(3.5, 0), 4.0)
|
---|
784 | self.assertEqual(round(4.5, 0), 5.0)
|
---|
785 | self.assertEqual(round(5.5, 0), 6.0)
|
---|
786 | self.assertEqual(round(6.5, 0), 7.0)
|
---|
787 |
|
---|
788 | # same but without an explicit second argument; in 3.x these
|
---|
789 | # will give integers
|
---|
790 | self.assertEqual(round(-6.5), -7.0)
|
---|
791 | self.assertEqual(round(-5.5), -6.0)
|
---|
792 | self.assertEqual(round(-1.5), -2.0)
|
---|
793 | self.assertEqual(round(-0.5), -1.0)
|
---|
794 | self.assertEqual(round(0.5), 1.0)
|
---|
795 | self.assertEqual(round(1.5), 2.0)
|
---|
796 | self.assertEqual(round(2.5), 3.0)
|
---|
797 | self.assertEqual(round(3.5), 4.0)
|
---|
798 | self.assertEqual(round(4.5), 5.0)
|
---|
799 | self.assertEqual(round(5.5), 6.0)
|
---|
800 | self.assertEqual(round(6.5), 7.0)
|
---|
801 |
|
---|
802 | self.assertEqual(round(-25.0, -1), -30.0)
|
---|
803 | self.assertEqual(round(-15.0, -1), -20.0)
|
---|
804 | self.assertEqual(round(-5.0, -1), -10.0)
|
---|
805 | self.assertEqual(round(5.0, -1), 10.0)
|
---|
806 | self.assertEqual(round(15.0, -1), 20.0)
|
---|
807 | self.assertEqual(round(25.0, -1), 30.0)
|
---|
808 | self.assertEqual(round(35.0, -1), 40.0)
|
---|
809 | self.assertEqual(round(45.0, -1), 50.0)
|
---|
810 | self.assertEqual(round(55.0, -1), 60.0)
|
---|
811 | self.assertEqual(round(65.0, -1), 70.0)
|
---|
812 | self.assertEqual(round(75.0, -1), 80.0)
|
---|
813 | self.assertEqual(round(85.0, -1), 90.0)
|
---|
814 | self.assertEqual(round(95.0, -1), 100.0)
|
---|
815 | self.assertEqual(round(12325.0, -1), 12330.0)
|
---|
816 |
|
---|
817 | self.assertEqual(round(350.0, -2), 400.0)
|
---|
818 | self.assertEqual(round(450.0, -2), 500.0)
|
---|
819 |
|
---|
820 | self.assertAlmostEqual(round(0.5e21, -21), 1e21)
|
---|
821 | self.assertAlmostEqual(round(1.5e21, -21), 2e21)
|
---|
822 | self.assertAlmostEqual(round(2.5e21, -21), 3e21)
|
---|
823 | self.assertAlmostEqual(round(5.5e21, -21), 6e21)
|
---|
824 | self.assertAlmostEqual(round(8.5e21, -21), 9e21)
|
---|
825 |
|
---|
826 | self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
|
---|
827 | self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
|
---|
828 | self.assertAlmostEqual(round(0.5e22, -22), 1e22)
|
---|
829 | self.assertAlmostEqual(round(1.5e22, -22), 2e22)
|
---|
830 |
|
---|
831 |
|
---|
832 | @requires_IEEE_754
|
---|
833 | def test_format_specials(self):
|
---|
834 | # Test formatting of nans and infs.
|
---|
835 |
|
---|
836 | def test(fmt, value, expected):
|
---|
837 | # Test with both % and format().
|
---|
838 | self.assertEqual(fmt % value, expected, fmt)
|
---|
839 | if not '#' in fmt:
|
---|
840 | # Until issue 7094 is implemented, format() for floats doesn't
|
---|
841 | # support '#' formatting
|
---|
842 | fmt = fmt[1:] # strip off the %
|
---|
843 | self.assertEqual(format(value, fmt), expected, fmt)
|
---|
844 |
|
---|
845 | for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
|
---|
846 | '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
|
---|
847 | pfmt = '%+' + fmt[1:]
|
---|
848 | sfmt = '% ' + fmt[1:]
|
---|
849 | test(fmt, INF, 'inf')
|
---|
850 | test(fmt, -INF, '-inf')
|
---|
851 | test(fmt, NAN, 'nan')
|
---|
852 | test(fmt, -NAN, 'nan')
|
---|
853 | # When asking for a sign, it's always provided. nans are
|
---|
854 | # always positive.
|
---|
855 | test(pfmt, INF, '+inf')
|
---|
856 | test(pfmt, -INF, '-inf')
|
---|
857 | test(pfmt, NAN, '+nan')
|
---|
858 | test(pfmt, -NAN, '+nan')
|
---|
859 | # When using ' ' for a sign code, only infs can be negative.
|
---|
860 | # Others have a space.
|
---|
861 | test(sfmt, INF, ' inf')
|
---|
862 | test(sfmt, -INF, '-inf')
|
---|
863 | test(sfmt, NAN, ' nan')
|
---|
864 | test(sfmt, -NAN, ' nan')
|
---|
865 |
|
---|
866 |
|
---|
867 | # Beginning with Python 2.6 float has cross platform compatible
|
---|
868 | # ways to create and represent inf and nan
|
---|
869 | class InfNanTest(unittest.TestCase):
|
---|
870 | def test_inf_from_str(self):
|
---|
871 | self.assertTrue(isinf(float("inf")))
|
---|
872 | self.assertTrue(isinf(float("+inf")))
|
---|
873 | self.assertTrue(isinf(float("-inf")))
|
---|
874 | self.assertTrue(isinf(float("infinity")))
|
---|
875 | self.assertTrue(isinf(float("+infinity")))
|
---|
876 | self.assertTrue(isinf(float("-infinity")))
|
---|
877 |
|
---|
878 | self.assertEqual(repr(float("inf")), "inf")
|
---|
879 | self.assertEqual(repr(float("+inf")), "inf")
|
---|
880 | self.assertEqual(repr(float("-inf")), "-inf")
|
---|
881 | self.assertEqual(repr(float("infinity")), "inf")
|
---|
882 | self.assertEqual(repr(float("+infinity")), "inf")
|
---|
883 | self.assertEqual(repr(float("-infinity")), "-inf")
|
---|
884 |
|
---|
885 | self.assertEqual(repr(float("INF")), "inf")
|
---|
886 | self.assertEqual(repr(float("+Inf")), "inf")
|
---|
887 | self.assertEqual(repr(float("-iNF")), "-inf")
|
---|
888 | self.assertEqual(repr(float("Infinity")), "inf")
|
---|
889 | self.assertEqual(repr(float("+iNfInItY")), "inf")
|
---|
890 | self.assertEqual(repr(float("-INFINITY")), "-inf")
|
---|
891 |
|
---|
892 | self.assertEqual(str(float("inf")), "inf")
|
---|
893 | self.assertEqual(str(float("+inf")), "inf")
|
---|
894 | self.assertEqual(str(float("-inf")), "-inf")
|
---|
895 | self.assertEqual(str(float("infinity")), "inf")
|
---|
896 | self.assertEqual(str(float("+infinity")), "inf")
|
---|
897 | self.assertEqual(str(float("-infinity")), "-inf")
|
---|
898 |
|
---|
899 | self.assertRaises(ValueError, float, "info")
|
---|
900 | self.assertRaises(ValueError, float, "+info")
|
---|
901 | self.assertRaises(ValueError, float, "-info")
|
---|
902 | self.assertRaises(ValueError, float, "in")
|
---|
903 | self.assertRaises(ValueError, float, "+in")
|
---|
904 | self.assertRaises(ValueError, float, "-in")
|
---|
905 | self.assertRaises(ValueError, float, "infinit")
|
---|
906 | self.assertRaises(ValueError, float, "+Infin")
|
---|
907 | self.assertRaises(ValueError, float, "-INFI")
|
---|
908 | self.assertRaises(ValueError, float, "infinitys")
|
---|
909 |
|
---|
910 | def test_inf_as_str(self):
|
---|
911 | self.assertEqual(repr(1e300 * 1e300), "inf")
|
---|
912 | self.assertEqual(repr(-1e300 * 1e300), "-inf")
|
---|
913 |
|
---|
914 | self.assertEqual(str(1e300 * 1e300), "inf")
|
---|
915 | self.assertEqual(str(-1e300 * 1e300), "-inf")
|
---|
916 |
|
---|
917 | def test_nan_from_str(self):
|
---|
918 | self.assertTrue(isnan(float("nan")))
|
---|
919 | self.assertTrue(isnan(float("+nan")))
|
---|
920 | self.assertTrue(isnan(float("-nan")))
|
---|
921 |
|
---|
922 | self.assertEqual(repr(float("nan")), "nan")
|
---|
923 | self.assertEqual(repr(float("+nan")), "nan")
|
---|
924 | self.assertEqual(repr(float("-nan")), "nan")
|
---|
925 |
|
---|
926 | self.assertEqual(repr(float("NAN")), "nan")
|
---|
927 | self.assertEqual(repr(float("+NAn")), "nan")
|
---|
928 | self.assertEqual(repr(float("-NaN")), "nan")
|
---|
929 |
|
---|
930 | self.assertEqual(str(float("nan")), "nan")
|
---|
931 | self.assertEqual(str(float("+nan")), "nan")
|
---|
932 | self.assertEqual(str(float("-nan")), "nan")
|
---|
933 |
|
---|
934 | self.assertRaises(ValueError, float, "nana")
|
---|
935 | self.assertRaises(ValueError, float, "+nana")
|
---|
936 | self.assertRaises(ValueError, float, "-nana")
|
---|
937 | self.assertRaises(ValueError, float, "na")
|
---|
938 | self.assertRaises(ValueError, float, "+na")
|
---|
939 | self.assertRaises(ValueError, float, "-na")
|
---|
940 |
|
---|
941 | def test_nan_as_str(self):
|
---|
942 | self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
|
---|
943 | self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
|
---|
944 |
|
---|
945 | self.assertEqual(str(1e300 * 1e300 * 0), "nan")
|
---|
946 | self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
|
---|
947 |
|
---|
948 | def notest_float_nan(self):
|
---|
949 | self.assertTrue(NAN.is_nan())
|
---|
950 | self.assertFalse(INF.is_nan())
|
---|
951 | self.assertFalse((0.).is_nan())
|
---|
952 |
|
---|
953 | def notest_float_inf(self):
|
---|
954 | self.assertTrue(INF.is_inf())
|
---|
955 | self.assertFalse(NAN.is_inf())
|
---|
956 | self.assertFalse((0.).is_inf())
|
---|
957 |
|
---|
958 | def test_hash_inf(self):
|
---|
959 | # the actual values here should be regarded as an
|
---|
960 | # implementation detail, but they need to be
|
---|
961 | # identical to those used in the Decimal module.
|
---|
962 | self.assertEqual(hash(float('inf')), 314159)
|
---|
963 | self.assertEqual(hash(float('-inf')), -271828)
|
---|
964 | self.assertEqual(hash(float('nan')), 0)
|
---|
965 |
|
---|
966 |
|
---|
967 | fromHex = float.fromhex
|
---|
968 | toHex = float.hex
|
---|
969 | class HexFloatTestCase(unittest.TestCase):
|
---|
970 | MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
|
---|
971 | MIN = fromHex('0x1p-1022') # min normal
|
---|
972 | TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
|
---|
973 | EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
|
---|
974 |
|
---|
975 | def identical(self, x, y):
|
---|
976 | # check that floats x and y are identical, or that both
|
---|
977 | # are NaNs
|
---|
978 | if isnan(x) or isnan(y):
|
---|
979 | if isnan(x) == isnan(y):
|
---|
980 | return
|
---|
981 | elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
|
---|
982 | return
|
---|
983 | self.fail('%r not identical to %r' % (x, y))
|
---|
984 |
|
---|
985 | def test_ends(self):
|
---|
986 | self.identical(self.MIN, ldexp(1.0, -1022))
|
---|
987 | self.identical(self.TINY, ldexp(1.0, -1074))
|
---|
988 | self.identical(self.EPS, ldexp(1.0, -52))
|
---|
989 | self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
|
---|
990 |
|
---|
991 | def test_invalid_inputs(self):
|
---|
992 | invalid_inputs = [
|
---|
993 | 'infi', # misspelt infinities and nans
|
---|
994 | '-Infinit',
|
---|
995 | '++inf',
|
---|
996 | '-+Inf',
|
---|
997 | '--nan',
|
---|
998 | '+-NaN',
|
---|
999 | 'snan',
|
---|
1000 | 'NaNs',
|
---|
1001 | 'nna',
|
---|
1002 | 'an',
|
---|
1003 | 'nf',
|
---|
1004 | 'nfinity',
|
---|
1005 | 'inity',
|
---|
1006 | 'iinity',
|
---|
1007 | '0xnan',
|
---|
1008 | '',
|
---|
1009 | ' ',
|
---|
1010 | 'x1.0p0',
|
---|
1011 | '0xX1.0p0',
|
---|
1012 | '+ 0x1.0p0', # internal whitespace
|
---|
1013 | '- 0x1.0p0',
|
---|
1014 | '0 x1.0p0',
|
---|
1015 | '0x 1.0p0',
|
---|
1016 | '0x1 2.0p0',
|
---|
1017 | '+0x1 .0p0',
|
---|
1018 | '0x1. 0p0',
|
---|
1019 | '-0x1.0 1p0',
|
---|
1020 | '-0x1.0 p0',
|
---|
1021 | '+0x1.0p +0',
|
---|
1022 | '0x1.0p -0',
|
---|
1023 | '0x1.0p 0',
|
---|
1024 | '+0x1.0p+ 0',
|
---|
1025 | '-0x1.0p- 0',
|
---|
1026 | '++0x1.0p-0', # double signs
|
---|
1027 | '--0x1.0p0',
|
---|
1028 | '+-0x1.0p+0',
|
---|
1029 | '-+0x1.0p0',
|
---|
1030 | '0x1.0p++0',
|
---|
1031 | '+0x1.0p+-0',
|
---|
1032 | '-0x1.0p-+0',
|
---|
1033 | '0x1.0p--0',
|
---|
1034 | '0x1.0.p0',
|
---|
1035 | '0x.p0', # no hex digits before or after point
|
---|
1036 | '0x1,p0', # wrong decimal point character
|
---|
1037 | '0x1pa',
|
---|
1038 | u'0x1p\uff10', # fullwidth Unicode digits
|
---|
1039 | u'\uff10x1p0',
|
---|
1040 | u'0x\uff11p0',
|
---|
1041 | u'0x1.\uff10p0',
|
---|
1042 | '0x1p0 \n 0x2p0',
|
---|
1043 | '0x1p0\0 0x1p0', # embedded null byte is not end of string
|
---|
1044 | ]
|
---|
1045 | for x in invalid_inputs:
|
---|
1046 | try:
|
---|
1047 | result = fromHex(x)
|
---|
1048 | except ValueError:
|
---|
1049 | pass
|
---|
1050 | else:
|
---|
1051 | self.fail('Expected float.fromhex(%r) to raise ValueError; '
|
---|
1052 | 'got %r instead' % (x, result))
|
---|
1053 |
|
---|
1054 |
|
---|
1055 | def test_whitespace(self):
|
---|
1056 | value_pairs = [
|
---|
1057 | ('inf', INF),
|
---|
1058 | ('-Infinity', -INF),
|
---|
1059 | ('nan', NAN),
|
---|
1060 | ('1.0', 1.0),
|
---|
1061 | ('-0x.2', -0.125),
|
---|
1062 | ('-0.0', -0.0)
|
---|
1063 | ]
|
---|
1064 | whitespace = [
|
---|
1065 | '',
|
---|
1066 | ' ',
|
---|
1067 | '\t',
|
---|
1068 | '\n',
|
---|
1069 | '\n \t',
|
---|
1070 | '\f',
|
---|
1071 | '\v',
|
---|
1072 | '\r'
|
---|
1073 | ]
|
---|
1074 | for inp, expected in value_pairs:
|
---|
1075 | for lead in whitespace:
|
---|
1076 | for trail in whitespace:
|
---|
1077 | got = fromHex(lead + inp + trail)
|
---|
1078 | self.identical(got, expected)
|
---|
1079 |
|
---|
1080 |
|
---|
1081 | def test_from_hex(self):
|
---|
1082 | MIN = self.MIN;
|
---|
1083 | MAX = self.MAX;
|
---|
1084 | TINY = self.TINY;
|
---|
1085 | EPS = self.EPS;
|
---|
1086 |
|
---|
1087 | # two spellings of infinity, with optional signs; case-insensitive
|
---|
1088 | self.identical(fromHex('inf'), INF)
|
---|
1089 | self.identical(fromHex('+Inf'), INF)
|
---|
1090 | self.identical(fromHex('-INF'), -INF)
|
---|
1091 | self.identical(fromHex('iNf'), INF)
|
---|
1092 | self.identical(fromHex('Infinity'), INF)
|
---|
1093 | self.identical(fromHex('+INFINITY'), INF)
|
---|
1094 | self.identical(fromHex('-infinity'), -INF)
|
---|
1095 | self.identical(fromHex('-iNFiNitY'), -INF)
|
---|
1096 |
|
---|
1097 | # nans with optional sign; case insensitive
|
---|
1098 | self.identical(fromHex('nan'), NAN)
|
---|
1099 | self.identical(fromHex('+NaN'), NAN)
|
---|
1100 | self.identical(fromHex('-NaN'), NAN)
|
---|
1101 | self.identical(fromHex('-nAN'), NAN)
|
---|
1102 |
|
---|
1103 | # variations in input format
|
---|
1104 | self.identical(fromHex('1'), 1.0)
|
---|
1105 | self.identical(fromHex('+1'), 1.0)
|
---|
1106 | self.identical(fromHex('1.'), 1.0)
|
---|
1107 | self.identical(fromHex('1.0'), 1.0)
|
---|
1108 | self.identical(fromHex('1.0p0'), 1.0)
|
---|
1109 | self.identical(fromHex('01'), 1.0)
|
---|
1110 | self.identical(fromHex('01.'), 1.0)
|
---|
1111 | self.identical(fromHex('0x1'), 1.0)
|
---|
1112 | self.identical(fromHex('0x1.'), 1.0)
|
---|
1113 | self.identical(fromHex('0x1.0'), 1.0)
|
---|
1114 | self.identical(fromHex('+0x1.0'), 1.0)
|
---|
1115 | self.identical(fromHex('0x1p0'), 1.0)
|
---|
1116 | self.identical(fromHex('0X1p0'), 1.0)
|
---|
1117 | self.identical(fromHex('0X1P0'), 1.0)
|
---|
1118 | self.identical(fromHex('0x1P0'), 1.0)
|
---|
1119 | self.identical(fromHex('0x1.p0'), 1.0)
|
---|
1120 | self.identical(fromHex('0x1.0p0'), 1.0)
|
---|
1121 | self.identical(fromHex('0x.1p4'), 1.0)
|
---|
1122 | self.identical(fromHex('0x.1p04'), 1.0)
|
---|
1123 | self.identical(fromHex('0x.1p004'), 1.0)
|
---|
1124 | self.identical(fromHex('0x1p+0'), 1.0)
|
---|
1125 | self.identical(fromHex('0x1P-0'), 1.0)
|
---|
1126 | self.identical(fromHex('+0x1p0'), 1.0)
|
---|
1127 | self.identical(fromHex('0x01p0'), 1.0)
|
---|
1128 | self.identical(fromHex('0x1p00'), 1.0)
|
---|
1129 | self.identical(fromHex(u'0x1p0'), 1.0)
|
---|
1130 | self.identical(fromHex(' 0x1p0 '), 1.0)
|
---|
1131 | self.identical(fromHex('\n 0x1p0'), 1.0)
|
---|
1132 | self.identical(fromHex('0x1p0 \t'), 1.0)
|
---|
1133 | self.identical(fromHex('0xap0'), 10.0)
|
---|
1134 | self.identical(fromHex('0xAp0'), 10.0)
|
---|
1135 | self.identical(fromHex('0xaP0'), 10.0)
|
---|
1136 | self.identical(fromHex('0xAP0'), 10.0)
|
---|
1137 | self.identical(fromHex('0xbep0'), 190.0)
|
---|
1138 | self.identical(fromHex('0xBep0'), 190.0)
|
---|
1139 | self.identical(fromHex('0xbEp0'), 190.0)
|
---|
1140 | self.identical(fromHex('0XBE0P-4'), 190.0)
|
---|
1141 | self.identical(fromHex('0xBEp0'), 190.0)
|
---|
1142 | self.identical(fromHex('0xB.Ep4'), 190.0)
|
---|
1143 | self.identical(fromHex('0x.BEp8'), 190.0)
|
---|
1144 | self.identical(fromHex('0x.0BEp12'), 190.0)
|
---|
1145 |
|
---|
1146 | # moving the point around
|
---|
1147 | pi = fromHex('0x1.921fb54442d18p1')
|
---|
1148 | self.identical(fromHex('0x.006487ed5110b46p11'), pi)
|
---|
1149 | self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
|
---|
1150 | self.identical(fromHex('0x.01921fb54442d18p9'), pi)
|
---|
1151 | self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
|
---|
1152 | self.identical(fromHex('0x.06487ed5110b46p7'), pi)
|
---|
1153 | self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
|
---|
1154 | self.identical(fromHex('0x.1921fb54442d18p5'), pi)
|
---|
1155 | self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
|
---|
1156 | self.identical(fromHex('0x.6487ed5110b46p3'), pi)
|
---|
1157 | self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
|
---|
1158 | self.identical(fromHex('0x1.921fb54442d18p1'), pi)
|
---|
1159 | self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
|
---|
1160 | self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
|
---|
1161 | self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
|
---|
1162 | self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
|
---|
1163 | self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
|
---|
1164 | self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
|
---|
1165 | self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
|
---|
1166 | self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
|
---|
1167 | self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
|
---|
1168 | self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
|
---|
1169 | self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
|
---|
1170 | self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
|
---|
1171 | # ...
|
---|
1172 | self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
|
---|
1173 | self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
|
---|
1174 | self.identical(fromHex('0x6487ed5110b46p-49'), pi)
|
---|
1175 | self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
|
---|
1176 | self.identical(fromHex('0x1921fb54442d18p-51'), pi)
|
---|
1177 | self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
|
---|
1178 | self.identical(fromHex('0x6487ed5110b460p-53'), pi)
|
---|
1179 | self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
|
---|
1180 | self.identical(fromHex('0x1921fb54442d180p-55'), pi)
|
---|
1181 |
|
---|
1182 |
|
---|
1183 | # results that should overflow...
|
---|
1184 | self.assertRaises(OverflowError, fromHex, '-0x1p1024')
|
---|
1185 | self.assertRaises(OverflowError, fromHex, '0x1p+1025')
|
---|
1186 | self.assertRaises(OverflowError, fromHex, '+0X1p1030')
|
---|
1187 | self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
|
---|
1188 | self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
|
---|
1189 | self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
|
---|
1190 | self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
|
---|
1191 | self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
|
---|
1192 | self.assertRaises(OverflowError, fromHex, '0X2p+1023')
|
---|
1193 | self.assertRaises(OverflowError, fromHex, '0x2.p1023')
|
---|
1194 | self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
|
---|
1195 | self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
|
---|
1196 | self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
|
---|
1197 | self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
|
---|
1198 | self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
|
---|
1199 | self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
|
---|
1200 | self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
|
---|
1201 | self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
|
---|
1202 | self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
|
---|
1203 |
|
---|
1204 | # ...and those that round to +-max float
|
---|
1205 | self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
|
---|
1206 | self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
|
---|
1207 | self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
|
---|
1208 |
|
---|
1209 | # zeros
|
---|
1210 | self.identical(fromHex('0x0p0'), 0.0)
|
---|
1211 | self.identical(fromHex('0x0p1000'), 0.0)
|
---|
1212 | self.identical(fromHex('-0x0p1023'), -0.0)
|
---|
1213 | self.identical(fromHex('0X0p1024'), 0.0)
|
---|
1214 | self.identical(fromHex('-0x0p1025'), -0.0)
|
---|
1215 | self.identical(fromHex('0X0p2000'), 0.0)
|
---|
1216 | self.identical(fromHex('0x0p123456789123456789'), 0.0)
|
---|
1217 | self.identical(fromHex('-0X0p-0'), -0.0)
|
---|
1218 | self.identical(fromHex('-0X0p-1000'), -0.0)
|
---|
1219 | self.identical(fromHex('0x0p-1023'), 0.0)
|
---|
1220 | self.identical(fromHex('-0X0p-1024'), -0.0)
|
---|
1221 | self.identical(fromHex('-0x0p-1025'), -0.0)
|
---|
1222 | self.identical(fromHex('-0x0p-1072'), -0.0)
|
---|
1223 | self.identical(fromHex('0X0p-1073'), 0.0)
|
---|
1224 | self.identical(fromHex('-0x0p-1074'), -0.0)
|
---|
1225 | self.identical(fromHex('0x0p-1075'), 0.0)
|
---|
1226 | self.identical(fromHex('0X0p-1076'), 0.0)
|
---|
1227 | self.identical(fromHex('-0X0p-2000'), -0.0)
|
---|
1228 | self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
|
---|
1229 |
|
---|
1230 | # values that should underflow to 0
|
---|
1231 | self.identical(fromHex('0X1p-1075'), 0.0)
|
---|
1232 | self.identical(fromHex('-0X1p-1075'), -0.0)
|
---|
1233 | self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
|
---|
1234 | self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
|
---|
1235 | self.identical(fromHex('-0x1.1p-1075'), -TINY)
|
---|
1236 | self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
|
---|
1237 |
|
---|
1238 | # check round-half-even is working correctly near 0 ...
|
---|
1239 | self.identical(fromHex('0x1p-1076'), 0.0)
|
---|
1240 | self.identical(fromHex('0X2p-1076'), 0.0)
|
---|
1241 | self.identical(fromHex('0X3p-1076'), TINY)
|
---|
1242 | self.identical(fromHex('0x4p-1076'), TINY)
|
---|
1243 | self.identical(fromHex('0X5p-1076'), TINY)
|
---|
1244 | self.identical(fromHex('0X6p-1076'), 2*TINY)
|
---|
1245 | self.identical(fromHex('0x7p-1076'), 2*TINY)
|
---|
1246 | self.identical(fromHex('0X8p-1076'), 2*TINY)
|
---|
1247 | self.identical(fromHex('0X9p-1076'), 2*TINY)
|
---|
1248 | self.identical(fromHex('0xap-1076'), 2*TINY)
|
---|
1249 | self.identical(fromHex('0Xbp-1076'), 3*TINY)
|
---|
1250 | self.identical(fromHex('0xcp-1076'), 3*TINY)
|
---|
1251 | self.identical(fromHex('0Xdp-1076'), 3*TINY)
|
---|
1252 | self.identical(fromHex('0Xep-1076'), 4*TINY)
|
---|
1253 | self.identical(fromHex('0xfp-1076'), 4*TINY)
|
---|
1254 | self.identical(fromHex('0x10p-1076'), 4*TINY)
|
---|
1255 | self.identical(fromHex('-0x1p-1076'), -0.0)
|
---|
1256 | self.identical(fromHex('-0X2p-1076'), -0.0)
|
---|
1257 | self.identical(fromHex('-0x3p-1076'), -TINY)
|
---|
1258 | self.identical(fromHex('-0X4p-1076'), -TINY)
|
---|
1259 | self.identical(fromHex('-0x5p-1076'), -TINY)
|
---|
1260 | self.identical(fromHex('-0x6p-1076'), -2*TINY)
|
---|
1261 | self.identical(fromHex('-0X7p-1076'), -2*TINY)
|
---|
1262 | self.identical(fromHex('-0X8p-1076'), -2*TINY)
|
---|
1263 | self.identical(fromHex('-0X9p-1076'), -2*TINY)
|
---|
1264 | self.identical(fromHex('-0Xap-1076'), -2*TINY)
|
---|
1265 | self.identical(fromHex('-0xbp-1076'), -3*TINY)
|
---|
1266 | self.identical(fromHex('-0xcp-1076'), -3*TINY)
|
---|
1267 | self.identical(fromHex('-0Xdp-1076'), -3*TINY)
|
---|
1268 | self.identical(fromHex('-0xep-1076'), -4*TINY)
|
---|
1269 | self.identical(fromHex('-0Xfp-1076'), -4*TINY)
|
---|
1270 | self.identical(fromHex('-0X10p-1076'), -4*TINY)
|
---|
1271 |
|
---|
1272 | # ... and near MIN ...
|
---|
1273 | self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
|
---|
1274 | self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
|
---|
1275 | self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
|
---|
1276 | self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
|
---|
1277 | self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
|
---|
1278 | self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
|
---|
1279 | self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
|
---|
1280 | self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
|
---|
1281 | self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
|
---|
1282 | self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
|
---|
1283 | self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
|
---|
1284 | self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
|
---|
1285 | self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
|
---|
1286 | self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
|
---|
1287 | self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
|
---|
1288 | self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
|
---|
1289 | self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
|
---|
1290 | self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
|
---|
1291 | self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
|
---|
1292 | self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
|
---|
1293 | self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
|
---|
1294 | self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
|
---|
1295 | self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
|
---|
1296 | self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
|
---|
1297 | self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
|
---|
1298 | self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
|
---|
1299 | self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
|
---|
1300 | self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
|
---|
1301 | self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
|
---|
1302 | self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
|
---|
1303 | self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
|
---|
1304 | self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
|
---|
1305 | self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
|
---|
1306 | self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
|
---|
1307 |
|
---|
1308 | # ... and near 1.0.
|
---|
1309 | self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
|
---|
1310 | self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
|
---|
1311 | self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
|
---|
1312 | self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
|
---|
1313 | self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
|
---|
1314 | self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
|
---|
1315 | self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
|
---|
1316 | self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
|
---|
1317 | self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
|
---|
1318 | self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
|
---|
1319 | self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
|
---|
1320 | self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
|
---|
1321 | self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
|
---|
1322 | self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
|
---|
1323 | self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
|
---|
1324 | self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
|
---|
1325 | self.identical(fromHex('0X1.00000000000000p0'), 1.0)
|
---|
1326 | self.identical(fromHex('0X1.00000000000001p0'), 1.0)
|
---|
1327 | self.identical(fromHex('0x1.00000000000002p0'), 1.0)
|
---|
1328 | self.identical(fromHex('0X1.00000000000003p0'), 1.0)
|
---|
1329 | self.identical(fromHex('0x1.00000000000004p0'), 1.0)
|
---|
1330 | self.identical(fromHex('0X1.00000000000005p0'), 1.0)
|
---|
1331 | self.identical(fromHex('0X1.00000000000006p0'), 1.0)
|
---|
1332 | self.identical(fromHex('0X1.00000000000007p0'), 1.0)
|
---|
1333 | self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
|
---|
1334 | 1.0)
|
---|
1335 | self.identical(fromHex('0x1.00000000000008p0'), 1.0)
|
---|
1336 | self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
|
---|
1337 | 1+EPS)
|
---|
1338 | self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
|
---|
1339 | self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
|
---|
1340 | self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
|
---|
1341 | self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
|
---|
1342 | self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
|
---|
1343 | self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
|
---|
1344 | self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
|
---|
1345 | self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
|
---|
1346 | self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
|
---|
1347 | self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
|
---|
1348 | self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
|
---|
1349 | self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
|
---|
1350 | self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
|
---|
1351 | self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
|
---|
1352 | self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
|
---|
1353 | self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
|
---|
1354 | 1.0+EPS)
|
---|
1355 | self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
|
---|
1356 | self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
|
---|
1357 | 1.0+2*EPS)
|
---|
1358 | self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
|
---|
1359 | self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
|
---|
1360 | self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
|
---|
1361 | self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
|
---|
1362 | self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
|
---|
1363 | self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
|
---|
1364 | self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
|
---|
1365 | self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
|
---|
1366 |
|
---|
1367 | def test_roundtrip(self):
|
---|
1368 | def roundtrip(x):
|
---|
1369 | return fromHex(toHex(x))
|
---|
1370 |
|
---|
1371 | for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
|
---|
1372 | self.identical(x, roundtrip(x))
|
---|
1373 | self.identical(-x, roundtrip(-x))
|
---|
1374 |
|
---|
1375 | # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
|
---|
1376 | import random
|
---|
1377 | for i in xrange(10000):
|
---|
1378 | e = random.randrange(-1200, 1200)
|
---|
1379 | m = random.random()
|
---|
1380 | s = random.choice([1.0, -1.0])
|
---|
1381 | try:
|
---|
1382 | x = s*ldexp(m, e)
|
---|
1383 | except OverflowError:
|
---|
1384 | pass
|
---|
1385 | else:
|
---|
1386 | self.identical(x, fromHex(toHex(x)))
|
---|
1387 |
|
---|
1388 |
|
---|
1389 | def test_main():
|
---|
1390 | test_support.run_unittest(
|
---|
1391 | GeneralFloatCases,
|
---|
1392 | FormatFunctionsTestCase,
|
---|
1393 | UnknownFormatTestCase,
|
---|
1394 | IEEEFormatTestCase,
|
---|
1395 | ReprTestCase,
|
---|
1396 | RoundTestCase,
|
---|
1397 | InfNanTest,
|
---|
1398 | HexFloatTestCase,
|
---|
1399 | )
|
---|
1400 |
|
---|
1401 | if __name__ == '__main__':
|
---|
1402 | test_main()
|
---|