Fixed #28280 -- Prevented numberformat.format() from formatting large/tiny floats in scientific notation.

This commit is contained in:
Hasan Ramezani 2020-02-23 14:37:02 +01:00 committed by Mariusz Felisiak
parent 667f784baa
commit bc1c034076
2 changed files with 27 additions and 4 deletions

View File

@ -26,6 +26,9 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
return mark_safe(number) return mark_safe(number)
# sign # sign
sign = '' sign = ''
# Treat potentially very large/small floats as Decimals.
if isinstance(number, float) and 'e' in str(number).lower():
number = Decimal(str(number))
if isinstance(number, Decimal): if isinstance(number, Decimal):
if decimal_pos is not None: if decimal_pos is not None:

View File

@ -55,10 +55,30 @@ class TestNumberFormat(SimpleTestCase):
self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-')) self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-'))
def test_float_numbers(self): def test_float_numbers(self):
# A float without a fractional part (3.) results in a ".0" when no tests = [
# decimal_pos is given. Contrast that with the Decimal('3.') case in (9e-10, 10, '0.0000000009'),
# test_decimal_numbers which doesn't return a fractional part. (9e-19, 2, '0.00'),
self.assertEqual(nformat(3., '.'), '3.0') (.00000000000099, 0, '0'),
(.00000000000099, 13, '0.0000000000009'),
(1e16, None, '10000000000000000'),
(1e16, 2, '10000000000000000.00'),
# A float without a fractional part (3.) results in a ".0" when no
# decimal_pos is given. Contrast that with the Decimal('3.') case
# in test_decimal_numbers which doesn't return a fractional part.
(3., None, '3.0'),
]
for value, decimal_pos, expected_value in tests:
with self.subTest(value=value, decimal_pos=decimal_pos):
self.assertEqual(nformat(value, '.', decimal_pos), expected_value)
# Thousand grouping behavior.
self.assertEqual(
nformat(1e16, '.', thousand_sep=',', grouping=3, force_grouping=True),
'10,000,000,000,000,000',
)
self.assertEqual(
nformat(1e16, '.', decimal_pos=2, thousand_sep=',', grouping=3, force_grouping=True),
'10,000,000,000,000,000.00',
)
def test_decimal_numbers(self): def test_decimal_numbers(self):
self.assertEqual(nformat(Decimal('1234'), '.'), '1234') self.assertEqual(nformat(Decimal('1234'), '.'), '1234')