diff --git a/babel/numbers.py b/babel/numbers.py index b684d8647..541e9ed85 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -525,16 +525,16 @@ def format_scientific( The format pattern can also be specified explicitly: - >>> format_scientific(1234567, u'##0E00', locale='en_US') - u'1E06' + >>> format_scientific(1234567, u'##0.##E00', locale='en_US') + u'1.23E06' By default the locale is allowed to truncate and round a high-precision number by forcing its format pattern onto the decimal part. You can bypass this behavior with the `decimal_quantization` parameter: - >>> format_scientific(1234.9876, locale='en_US') - u'1E3' - >>> format_scientific(1234.9876, locale='en_US', decimal_quantization=False) + >>> format_scientific(1234.9876, u'#.##E0', locale='en_US') + u'1.23E3' + >>> format_scientific(1234.9876, u'#.##E0', locale='en_US', decimal_quantization=False) u'1.2349876E3' :param number: the number to format @@ -796,8 +796,12 @@ def apply( frac_prec = (get_currency_precision(currency), ) * 2 # Bump decimal precision to the natural precision of the number if it - # exceeds the one we're about to use. - if not decimal_quantization: + # exceeds the one we're about to use. This adaptative precision is only + # triggered if the decimal quantization is disabled or if a scientific + # notation pattern has a missing mandatory fractional part (as in the + # default '#E0' pattern). This special case has been extensively + # disccused at https://github.com/python-babel/babel/pull/494#issuecomment-307649969 . + if not decimal_quantization or (self.exp_prec and frac_prec == (0, 0)): frac_prec = (frac_prec[0], max([frac_prec[1], get_decimal_precision(value)])) # Render scientific notation. diff --git a/tests/test_numbers.py b/tests/test_numbers.py index 03164ebbb..03a4c9b08 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -467,14 +467,25 @@ def test_format_percent_quantization(): def test_format_scientific(): assert numbers.format_scientific(10000, locale='en_US') == u'1E4' assert numbers.format_scientific(4234567, u'#.#E0', locale='en_US') == u'4.2E6' - assert numbers.format_scientific(4234567, u'0E0000', locale='en_US') == u'4E0006' - assert numbers.format_scientific(4234567, u'##0E00', locale='en_US') == u'4E06' - assert numbers.format_scientific(4234567, u'##00E00', locale='en_US') == u'42E05' - assert numbers.format_scientific(4234567, u'0,000E00', locale='en_US') == u'4,235E03' + assert numbers.format_scientific(4234567, u'0E0000', locale='en_US') == u'4.234567E0006' + assert numbers.format_scientific(4234567, u'##0E00', locale='en_US') == u'4.234567E06' + assert numbers.format_scientific(4234567, u'##00E00', locale='en_US') == u'42.34567E05' + assert numbers.format_scientific(4234567, u'0,000E00', locale='en_US') == u'4,234.567E03' assert numbers.format_scientific(4234567, u'##0.#####E00', locale='en_US') == u'4.23457E06' + assert numbers.format_scientific(4234567, u'##0.##E00', locale='en_US') == u'4.23E06' assert numbers.format_scientific(42, u'00000.000000E0000', locale='en_US') == u'42000.000000E-0003' +def test_default_scientific_format(): + """ Check the scientific format method auto-correct the rendering pattern + in case of a missing fractional part. + """ + assert numbers.format_scientific(12345, locale='en_US') == u'1.2345E4' + assert numbers.format_scientific(12345.678, locale='en_US') == u'1.2345678E4' + assert numbers.format_scientific(12345, u'#E0', locale='en_US') == u'1.2345E4' + assert numbers.format_scientific(12345.678, u'#E0', locale='en_US') == u'1.2345678E4' + + @pytest.mark.parametrize('input_value, expected_value', [ ('10000', '1E4'), ('1', '1E0'),