changeset 557:4e561e6411ba trunk

Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
author fschwarz
date Tue, 30 Aug 2011 20:53:33 +0000
parents aa53048ad7ac
children 8831b754f81e
files ChangeLog babel/numbers.py babel/tests/numbers.py
diffstat 3 files changed, 24 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -31,6 +31,9 @@
    handlers (#227, reported with initial patch by dfraser)
  * Fix exception if environment contains an invalid locale setting (#200)
  * use cPickle instead of pickle for better performance (#225)
+ * Only use bankers round algorithm as a tie breaker if there are two nearest
+   numbers, round as usual if there is only one nearest number (#267, patch by 
+   Martin)
 
 
 Version 0.9.6
--- a/babel/numbers.py
+++ b/babel/numbers.py
@@ -361,6 +361,13 @@
         add = 1
     elif digits[i] == '5' and digits[i-1] in '13579':
         add = 1
+    elif digits[i] == '5':     # previous digit is even
+        # We round up unless all following digits are zero.
+        for j in xrange(i + 1, len(digits)):
+            if digits[j] != '0':
+                add = 1
+                break
+
     scale = 10**ndigits
     if isinstance(value, Decimal):
         return Decimal(int(value * scale + add)) / scale * sign
--- a/babel/tests/numbers.py
+++ b/babel/tests/numbers.py
@@ -12,7 +12,6 @@
 # history and logs, available at http://babel.edgewall.org/log/.
 
 from decimal import Decimal
-
 import doctest
 import unittest
 
@@ -137,10 +136,24 @@
         self.assertEqual(fmt, '0E0')
 
 
+class BankersRoundTestCase(unittest.TestCase):
+    def test_round_to_nearest_integer(self):
+        self.assertEqual(1, numbers.bankersround(Decimal('0.5001')))
+    
+    def test_round_to_even_for_two_nearest_integers(self):
+        self.assertEqual(0, numbers.bankersround(Decimal('0.5')))
+        self.assertEqual(2, numbers.bankersround(Decimal('1.5')))
+        self.assertEqual(-2, numbers.bankersround(Decimal('-2.5')))
+
+        self.assertEqual(0, numbers.bankersround(Decimal('0.05'), ndigits=1))
+        self.assertEqual(Decimal('0.2'), numbers.bankersround(Decimal('0.15'), ndigits=1))
+
+
 def suite():
     suite = unittest.TestSuite()
     suite.addTest(doctest.DocTestSuite(numbers))
     suite.addTest(unittest.makeSuite(FormatDecimalTestCase))
+    suite.addTest(unittest.makeSuite(BankersRoundTestCase))
     return suite
 
 if __name__ == '__main__':
Copyright (C) 2012-2017 Edgewall Software