From cd7118237717c925aefa73157cb53277d3f2f4a8 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Sun, 28 Jun 2026 13:03:50 +0200 Subject: [PATCH] Fix format_number producing bogus output for integers >= 10**16 When format_number() receives an integer >= 10**16, str(float(number)) produces scientific notation (e.g. '1e+16'). The subsequent .partition('.') call then returns ('1e+16', '', '') since there is no decimal point, and the comma-insertion loop operates on the '1e+...' text as if it were plain digits, yielding garbage output like '1e,+16'. Fix by short-circuiting the float conversion for plain int types (using type(x) is int) and using str(number) directly instead. This preserves the exact decimal representation and lets the existing comma-insertion and sign logic work correctly. Fixes a wrong-results bug where format_number(10**16) returned '1e,+16' instead of '10,000,000,000,000,000'. --- humanfriendly/__init__.py | 6 ++++++ humanfriendly/tests.py | 4 ++++ 2 files changed, 10 insertions(+) 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()`."""