mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue #1869 (and 4707, 5118, 5473, 1456775): use the new
string <-> float conversion routines to make round(x, n) correctly rounded for floats x, so that it always agrees with format(x, '.<n>f'). Also fix some other round nuisances, like round(123.456, 1-2**31) giving an integer rather than a float.
This commit is contained in:
parent
60fd0999cc
commit
e6a076d86c
3 changed files with 234 additions and 28 deletions
|
@ -389,6 +389,88 @@ class ReprTestCase(unittest.TestCase):
|
|||
self.assertEqual(s, repr(float(s)))
|
||||
self.assertEqual(negs, repr(float(negs)))
|
||||
|
||||
class RoundTestCase(unittest.TestCase):
|
||||
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
|
||||
"test requires IEEE 754 doubles")
|
||||
def test_inf_nan(self):
|
||||
self.assertRaises(OverflowError, round, INF)
|
||||
self.assertRaises(OverflowError, round, -INF)
|
||||
self.assertRaises(ValueError, round, NAN)
|
||||
|
||||
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
|
||||
"test requires IEEE 754 doubles")
|
||||
def test_large_n(self):
|
||||
for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
|
||||
self.assertEqual(round(123.456, n), 123.456)
|
||||
self.assertEqual(round(-123.456, n), -123.456)
|
||||
self.assertEqual(round(1e300, n), 1e300)
|
||||
self.assertEqual(round(1e-320, n), 1e-320)
|
||||
self.assertEqual(round(1e150, 300), 1e150)
|
||||
self.assertEqual(round(1e300, 307), 1e300)
|
||||
self.assertEqual(round(-3.1415, 308), -3.1415)
|
||||
self.assertEqual(round(1e150, 309), 1e150)
|
||||
self.assertEqual(round(1.4e-315, 315), 1e-315)
|
||||
|
||||
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
|
||||
"test requires IEEE 754 doubles")
|
||||
def test_small_n(self):
|
||||
for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
|
||||
self.assertEqual(round(123.456, n), 0.0)
|
||||
self.assertEqual(round(-123.456, n), -0.0)
|
||||
self.assertEqual(round(1e300, n), 0.0)
|
||||
self.assertEqual(round(1e-320, n), 0.0)
|
||||
|
||||
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
|
||||
"test requires IEEE 754 doubles")
|
||||
def test_overflow(self):
|
||||
self.assertRaises(OverflowError, round, 1.6e308, -308)
|
||||
self.assertRaises(OverflowError, round, -1.7e308, -308)
|
||||
|
||||
@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
|
||||
"applies only when using short float repr style")
|
||||
def test_previous_round_bugs(self):
|
||||
# particular cases that have occurred in bug reports
|
||||
self.assertEqual(round(562949953421312.5, 1),
|
||||
562949953421312.5)
|
||||
self.assertEqual(round(56294995342131.5, 3),
|
||||
56294995342131.5)
|
||||
# round-half-even
|
||||
self.assertEqual(round(25.0, -1), 20.0)
|
||||
self.assertEqual(round(35.0, -1), 40.0)
|
||||
self.assertEqual(round(45.0, -1), 40.0)
|
||||
self.assertEqual(round(55.0, -1), 60.0)
|
||||
self.assertEqual(round(65.0, -1), 60.0)
|
||||
self.assertEqual(round(75.0, -1), 80.0)
|
||||
self.assertEqual(round(85.0, -1), 80.0)
|
||||
self.assertEqual(round(95.0, -1), 100.0)
|
||||
|
||||
@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
|
||||
"applies only when using short float repr style")
|
||||
def test_matches_float_format(self):
|
||||
# round should give the same results as float formatting
|
||||
for i in range(500):
|
||||
x = i/1000.
|
||||
self.assertEqual(float(format(x, '.0f')), round(x, 0))
|
||||
self.assertEqual(float(format(x, '.1f')), round(x, 1))
|
||||
self.assertEqual(float(format(x, '.2f')), round(x, 2))
|
||||
self.assertEqual(float(format(x, '.3f')), round(x, 3))
|
||||
|
||||
for i in range(5, 5000, 10):
|
||||
x = i/1000.
|
||||
self.assertEqual(float(format(x, '.0f')), round(x, 0))
|
||||
self.assertEqual(float(format(x, '.1f')), round(x, 1))
|
||||
self.assertEqual(float(format(x, '.2f')), round(x, 2))
|
||||
self.assertEqual(float(format(x, '.3f')), round(x, 3))
|
||||
|
||||
for i in range(500):
|
||||
x = random.random()
|
||||
self.assertEqual(float(format(x, '.0f')), round(x, 0))
|
||||
self.assertEqual(float(format(x, '.1f')), round(x, 1))
|
||||
self.assertEqual(float(format(x, '.2f')), round(x, 2))
|
||||
self.assertEqual(float(format(x, '.3f')), round(x, 3))
|
||||
|
||||
|
||||
|
||||
# Beginning with Python 2.6 float has cross platform compatible
|
||||
# ways to create and represent inf and nan
|
||||
class InfNanTest(unittest.TestCase):
|
||||
|
@ -878,6 +960,7 @@ def test_main():
|
|||
IEEEFormatTestCase,
|
||||
FormatTestCase,
|
||||
ReprTestCase,
|
||||
RoundTestCase,
|
||||
InfNanTest,
|
||||
HexFloatTestCase,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue