Created
July 9, 2017 14:56
-
-
Save ncoghlan/93e758e73a20dd864be99fb1faa5ce29 to your computer and use it in GitHub Desktop.
Checking Python's rounding behaviour
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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