Created
May 27, 2014 13:40
-
-
Save kentquirk/3644a03c6a037b7cf0ba to your computer and use it in GitHub Desktop.
Shows how storing data in ints is a problem but in floats works just fine
This file contains hidden or 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
# This is a small program that tests conversion to and from different formats | |
# and makes sure that numbers that undergo conversion don't lose precision. | |
import math | |
# truncates a number to the given number of digits after the decimal | |
def truncate(x, digits): | |
p = math.pow(10, digits) | |
return int(x * p)/p | |
def round(x, digits): | |
p = math.pow(10, digits) | |
return int(x * p + 0.5)/p | |
# prove that they work, more or less | |
assert(truncate(math.pi, 0) == 3) | |
assert(truncate(math.pi, 2) == 3.14) | |
assert(truncate(math.pi, 4) == 3.1415) | |
assert(truncate(1.5, 0) == 1) | |
assert(round(math.pi, 0) == 3) | |
assert(round(math.pi, 2) == 3.14) | |
assert(round(math.pi, 4) == 3.1416) | |
assert(round(1.5, 0) == 2) | |
# now let's deal with conversions | |
conversion = 18.01559 | |
def cvt_Euro_US(bg): | |
return bg * conversion | |
def cvt_US_Euro(bg): | |
return bg / conversion | |
US_samples = [ 40, 67, 95, 120, 240, 450 ] | |
Euro_samples = [ 2.2, 3.7, 5.3, 6.6, 13.3, 24.9 ] | |
def store_US_as_US_int(x): | |
storedValue = int(x) | |
fetchedValue = storedValue | |
return fetchedValue | |
def store_Euro_as_US_int(x): | |
storedValue = int(cvt_Euro_US(x)) | |
fetchedValue = truncate(storedValue, 1) | |
return fetchedValue | |
def store_US_as_Euro_float(x): | |
storedValue = cvt_US_Euro(x) | |
fetchedValue = round(x, 0) | |
return fetchedValue | |
def store_Euro_as_Euro_float(x): | |
storedValue = x | |
fetchedValue = round(x, 1) | |
return fetchedValue | |
def store_US_as_US_float(x): | |
storedValue = float(x) | |
fetchedValue = round(x, 0) | |
return fetchedValue | |
def store_Euro_as_US_float(x): | |
storedValue = cvt_Euro_US(x) | |
fetchedValue = round(x, 1) | |
return fetchedValue | |
def test(f, values): | |
print "*** %s ***" % f.__name__ | |
failed = False | |
for v in values: | |
try: | |
assert(v == f(v)) | |
except AssertionError: | |
print " Failed on %s" % v | |
failed = True | |
if not failed: | |
print " All good." | |
# Test our sample values | |
print "If we store things as integers, it works fine for US values" | |
test(store_US_as_US_int, US_samples) | |
print "But it fails for euro values" | |
test(store_Euro_as_US_int, Euro_samples) # this is the only test that fails | |
print "But if we store as floating point Euro values, it all works fine" | |
test(store_US_as_Euro_float, US_samples) | |
test(store_Euro_as_Euro_float, Euro_samples) | |
print "We can even store as US, even if we use floating point." | |
test(store_US_as_Euro_float, US_samples) | |
test(store_Euro_as_Euro_float, Euro_samples) | |
print "And to prove it, let's test all US values from 0 to 2000" | |
test(store_US_as_Euro_float, range(2000)) | |
print "And again with all Euro values from 0 to 50" | |
test(store_Euro_as_Euro_float, [round(x/10.0, 1) for x in range(500)]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment