diff --git a/humanfriendly/__init__.py b/humanfriendly/__init__.py index 4c0a333..1745cee 100644 --- a/humanfriendly/__init__.py +++ b/humanfriendly/__init__.py @@ -353,6 +353,12 @@ def format_number(number, num_decimals=2): 6,000,000,000 """ integer_part, _, decimal_part = str(float(number)).partition('.') + + # Avoid float conversion for integers to prevent bogus output when + # str(float()) uses scientific notation (numbers >= 10**16). + if type(number) is int: + integer_part = str(number) + decimal_part = '' negative_sign = integer_part.startswith('-') reversed_digits = ''.join(reversed(integer_part.lstrip('-'))) parts = [] diff --git a/humanfriendly/tests.py b/humanfriendly/tests.py index 72dad99..d92742e 100644 --- a/humanfriendly/tests.py +++ b/humanfriendly/tests.py @@ -577,6 +577,10 @@ def test_format_number(self): self.assertEqual('1,000,000.42', format_number(1000000.42)) # Regression test for https://github.com/xolox/python-humanfriendly/issues/40. self.assertEqual('-285.67', format_number(-285.67)) + # Regression test for integer inputs >= 10**16 where float conversion + # produces scientific notation that corrupts the output. + self.assertEqual('10,000,000,000,000,000', format_number(10 ** 16)) + self.assertEqual('1,000,000,000,000,000,000', format_number(10 ** 18)) def test_round_number(self): """Test :func:`humanfriendly.round_number()`."""