]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
fix format_decimal() with small Decimal values (#214, patch from George Lund)
authorFelix Schwarz <felix.schwarz@oss.schwarz.eu>
Fri, 3 Aug 2012 08:36:21 +0000 (08:36 +0000)
committerFelix Schwarz <felix.schwarz@oss.schwarz.eu>
Fri, 3 Aug 2012 08:36:21 +0000 (08:36 +0000)
ChangeLog
babel/numbers.py
babel/tests/numbers.py

index eea3eb02ae7962609f7b9be2dc1be7c4c7104325..905e43f5328ff5b6c02c56528f08615784fd66e0 100644 (file)
--- 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
index 795a0fa25d9a5533b5902dc417fe8537babe97ff..97d857bf7b0b75af8262ab194c37f77fe536b40a 100644 (file)
@@ -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':
index caaa1d08b9c8baa61e989cec19ed5b4a0c39aac8..6a19ee6077be66f2084257ea5662c8beda163b4c 100644 (file)
@@ -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):