diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-04-20 21:38:00 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-04-20 21:38:00 (GMT) |
commit | c630039edd7526642ffdaeee3bfa81352b5c98ae (patch) | |
tree | 08e885e766a83d689c499522c873e04fcd93cb8f /Lib/test | |
parent | 628fbd59ea2819e55e81ca21bbb52e7d5f4cface (diff) | |
download | cpython-c630039edd7526642ffdaeee3bfa81352b5c98ae.zip cpython-c630039edd7526642ffdaeee3bfa81352b5c98ae.tar.gz cpython-c630039edd7526642ffdaeee3bfa81352b5c98ae.tar.bz2 |
Merged revisions 71772 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r71772 | mark.dickinson | 2009-04-20 22:13:33 +0100 (Mon, 20 Apr 2009) | 5 lines
Issue #3166: Make long -> float (and int -> float) conversions
correctly rounded, using round-half-to-even. This ensures that the
value of float(n) doesn't depend on whether we're using 15-bit digits
or 30-bit digits for Python longs.
........
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_long.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 92285b2..53d3e6b 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -620,6 +620,65 @@ class LongTest(unittest.TestCase): else: self.assertRaises(TypeError, pow,longx, longy, int(z)) + @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), + "test requires IEEE 754 doubles") + def test_float_conversion(self): + import sys + DBL_MAX = sys.float_info.max + DBL_MAX_EXP = sys.float_info.max_exp + DBL_MANT_DIG = sys.float_info.mant_dig + + exact_values = [0, 1, 2, + 2**53-3, + 2**53-2, + 2**53-1, + 2**53, + 2**53+2, + 2**54-4, + 2**54-2, + 2**54, + 2**54+4] + for x in exact_values: + self.assertEqual(float(x), x) + self.assertEqual(float(-x), -x) + + # test round-half-even + for x, y in [(1, 0), (2, 2), (3, 4), (4, 4), (5, 4), (6, 6), (7, 8)]: + for p in range(15): + self.assertEqual(int(float(2**p*(2**53+x))), 2**p*(2**53+y)) + + for x, y in [(0, 0), (1, 0), (2, 0), (3, 4), (4, 4), (5, 4), (6, 8), + (7, 8), (8, 8), (9, 8), (10, 8), (11, 12), (12, 12), + (13, 12), (14, 16), (15, 16)]: + for p in range(15): + self.assertEqual(int(float(2**p*(2**54+x))), 2**p*(2**54+y)) + + # behaviour near extremes of floating-point range + int_dbl_max = int(DBL_MAX) + top_power = 2**DBL_MAX_EXP + halfway = (int_dbl_max + top_power)//2 + self.assertEqual(float(int_dbl_max), DBL_MAX) + self.assertEqual(float(int_dbl_max+1), DBL_MAX) + self.assertEqual(float(halfway-1), DBL_MAX) + self.assertRaises(OverflowError, float, halfway) + self.assertEqual(float(1-halfway), -DBL_MAX) + self.assertRaises(OverflowError, float, -halfway) + self.assertRaises(OverflowError, float, top_power-1) + self.assertRaises(OverflowError, float, top_power) + self.assertRaises(OverflowError, float, top_power+1) + self.assertRaises(OverflowError, float, 2*top_power-1) + self.assertRaises(OverflowError, float, 2*top_power) + self.assertRaises(OverflowError, float, top_power*top_power) + + for p in range(100): + x = 2**p * (2**53 + 1) + 1 + y = 2**p * (2**53 + 2) + self.assertEqual(int(float(x)), y) + + x = 2**p * (2**53 + 1) + y = 2**p * 2**53 + self.assertEqual(int(float(x)), y) + def test_float_overflow(self): import math |