Skip to content

Instantly share code, notes, and snippets.

@ncoghlan
Created July 9, 2017 14:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ncoghlan/93e758e73a20dd864be99fb1faa5ce29 to your computer and use it in GitHub Desktop.
Save ncoghlan/93e758e73a20dd864be99fb1faa5ce29 to your computer and use it in GitHub Desktop.
Checking Python's rounding behaviour
# Prompted by this article about implementing "Round half away from zero" in Go
# https://www.cockroachlabs.com/blog/rounding-implementations-in-go/
# Python uses round-half-even by default to reduce statistical bias,
# but round-half-away-from-zero can be implemented more efficiently
# (since it doesn't need to examine all the bits of the number)
# I figured the folks doing computational analysis in Python would
# have made sure this was handled correctly years ago, but it never
# hurts to check that kind of assumption :)
import sys
import math
epsilon = sys.float_info.epsilon
round_half_even = {
-0.5+epsilon: -0.0,
-0.5: -0.0,
-0.5-epsilon: -1,
0.0: 0.0,
0.5-epsilon: 0,
0.5: 0,
0.5+epsilon: 1,
1.390671161567e-309: 0,
2.2517998136852485e+15: 2.251799813685248e+15,
4.503599627370497e+15: 4.503599627370497e+15,
-math.inf: -math.inf,
math.inf: math.inf,
math.nan: math.nan,
-0.0: -0.0,
}
as_expected = []
discrepancy = []
for original, rounded in round_half_even.items():
actual = round(original)
if rounded != actual:
discrepancy.append((original, rounded, actual))
else:
as_expected.append((original, rounded))
if as_expected:
print("The following cases rounded as expected:")
for original, rounded in as_expected:
print(f" {original} -> {rounded}")
if discrepancy:
print("The following cases failed to give the expected result:")
for original, expected, actual in discrepancy:
print(f" {original} -> {actual}, *not* {expected}")
The following cases rounded as expected:
-0.4999999999999998 -> -0.0
-0.5 -> -0.0
-0.5000000000000002 -> -1
0.0 -> -0.0
0.4999999999999998 -> 0
0.5 -> 0
0.5000000000000002 -> 1
1.390671161567e-309 -> 0
2251799813685248.5 -> 2251799813685248.0
4503599627370497.0 -> 4503599627370497.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment