Skip to content

Instantly share code, notes, and snippets.

@gsakkis
Created March 12, 2012 09:11
Show Gist options
  • Save gsakkis/2020833 to your computer and use it in GitHub Desktop.
Save gsakkis/2020833 to your computer and use it in GitHub Desktop.
Python decimal rounding behavior
-2.695
reduced by ROUND_UP, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_EVEN
increased by ROUND_DOWN, ROUND_05UP, ROUND_CEILING, ROUND_HALF_DOWN
-2.669, -2.699
reduced by ROUND_UP, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_DOWN, ROUND_05UP, ROUND_CEILING
-2.665
reduced by ROUND_UP, ROUND_FLOOR, ROUND_HALF_UP
increased by ROUND_DOWN, ROUND_05UP, ROUND_CEILING, ROUND_HALF_DOWN, ROUND_HALF_EVEN
-2.661, -2.691
reduced by ROUND_UP, ROUND_FLOOR
increased by ROUND_DOWN, ROUND_05UP, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
-2.655
reduced by ROUND_UP, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_EVEN
increased by ROUND_DOWN, ROUND_CEILING, ROUND_HALF_DOWN
-2.609, -2.659
reduced by ROUND_UP, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_DOWN, ROUND_CEILING
-2.605
reduced by ROUND_UP, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_UP
increased by ROUND_DOWN, ROUND_CEILING, ROUND_HALF_DOWN, ROUND_HALF_EVEN
-2.601, -2.651
reduced by ROUND_UP, ROUND_05UP, ROUND_FLOOR
increased by ROUND_DOWN, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
2.601, 2.651
reduced by ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_UP, ROUND_05UP, ROUND_CEILING
2.605
reduced by ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_UP, ROUND_05UP, ROUND_CEILING, ROUND_HALF_UP
2.609, 2.659
reduced by ROUND_DOWN, ROUND_FLOOR
increased by ROUND_UP, ROUND_05UP, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
2.655
reduced by ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN
increased by ROUND_UP, ROUND_05UP, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_EVEN
2.661, 2.691
reduced by ROUND_DOWN, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_UP, ROUND_CEILING
2.665
reduced by ROUND_DOWN, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN
increased by ROUND_UP, ROUND_CEILING, ROUND_HALF_UP
2.669, 2.699
reduced by ROUND_DOWN, ROUND_05UP, ROUND_FLOOR
increased by ROUND_UP, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN
2.695
reduced by ROUND_DOWN, ROUND_05UP, ROUND_FLOOR, ROUND_HALF_DOWN
increased by ROUND_UP, ROUND_CEILING, ROUND_HALF_UP, ROUND_HALF_EVEN
import decimal as d
from collections import defaultdict
from operator import itemgetter
exp = d.Decimal("0.01")
numbers = map(d.Decimal, [
"-2.601", "-2.605", "-2.609",
"-2.651", "-2.655", "-2.659",
"-2.661", "-2.665", "-2.669",
"-2.691", "-2.695", "-2.699",
"2.601", "2.605", "2.609",
"2.651", "2.655", "2.659",
"2.661", "2.665", "2.669",
"2.691", "2.695", "2.699",
])
roundings = [
d.ROUND_UP,
d.ROUND_DOWN,
d.ROUND_05UP,
d.ROUND_FLOOR,
d.ROUND_CEILING,
d.ROUND_HALF_UP,
d.ROUND_HALF_DOWN,
d.ROUND_HALF_EVEN,
]
groups = defaultdict(list)
for n in numbers:
reduced, increased = [], []
for r in roundings:
q = n.quantize(exp, r)
if q > n:
increased.append(r)
elif q < n:
reduced.append(r)
if reduced or increased:
groups[tuple(reduced), tuple(increased)].append(n)
assert len(groups) <= 16, len(groups)
for (reduced, increased), group in sorted(groups.iteritems(), key=itemgetter(1)):
print ", ".join(map(str, group))
print " reduced by", ", ".join(reduced)
print " increased by", ", ".join(increased)
@tokland
Copy link

tokland commented Oct 20, 2015

That was really helpful, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment