From: Felix Schwarz Date: Fri, 3 Aug 2012 08:36:21 +0000 (+0000) Subject: fix format_decimal() with small Decimal values (#214, patch from George Lund) X-Git-Tag: 1.0~167 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5919a7da20b3fbbe40cd0b2a29ab2e12e4fad42b;p=thirdparty%2Fbabel.git fix format_decimal() with small Decimal values (#214, patch from George Lund) --- diff --git a/ChangeLog b/ChangeLog index eea3eb02..905e43f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,7 @@ http://svn.edgewall.org/repos/babel/tags/1.0.0/ * fix formatting of fraction in format_decimal() if the input value is a float with more than 7 significant digits (#183) * fix format_date() with datetime parameter (#282, patch from Xavier Morel) + * fix format_decimal() with small Decimal values (#214, patch from George Lund) Version 0.9.6 diff --git a/babel/numbers.py b/babel/numbers.py index 795a0fa2..97d857bf 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -323,9 +323,39 @@ number_re = re.compile(r"%s%s%s" % (PREFIX_PATTERN, NUMBER_PATTERN, def split_number(value): """Convert a number into a (intasstring, fractionasstring) tuple""" if isinstance(value, Decimal): - text = str(value) - else: - text = ('%.9f' % value).rstrip('0') + # NB can't just do text = str(value) as str repr of Decimal may be + # in scientific notation, e.g. for small numbers. + + sign, digits, exp = value.as_tuple() + # build list of digits in reverse order, then reverse+join + # as per http://docs.python.org/library/decimal.html#recipes + int_part = [] + frac_part = [] + + digits = map(str, digits) + + # get figures after decimal point + for i in range(-exp): + # add digit if available, else 0 + frac_part.append(digits.pop() if digits else '0') + + # add in some zeroes... + for i in range(exp): + int_part.append('0') + + # and the rest + while digits: + int_part.append(digits.pop()) + + # if < 1, int_part must be set to '0' + if len(int_part) == 0: + int_part = '0', + + if sign: + int_part.append('-') + + return ''.join(reversed(int_part)), ''.join(reversed(frac_part)) + text = ('%.9f' % value).rstrip('0') if '.' in text: a, b = text.split('.', 1) if b == '0': diff --git a/babel/tests/numbers.py b/babel/tests/numbers.py index caaa1d08..6a19ee60 100644 --- a/babel/tests/numbers.py +++ b/babel/tests/numbers.py @@ -140,6 +140,13 @@ class FormatDecimalTestCase(unittest.TestCase): # 0 (see ticket #99) fmt = numbers.format_scientific(0, '#E0', locale='en_US') self.assertEqual(fmt, '0E0') + + def test_formatting_of_very_small_decimals(self): + # previously formatting very small decimals could lead to a type error + # because the Decimal->string conversion was too simple (see #214) + number = Decimal("7E-7") + fmt = numbers.format_decimal(number, format="@@@", locale='en_US') + self.assertEqual('0.000000700', fmt) class BankersRoundTestCase(unittest.TestCase):