Created
November 14, 2016 13:56
-
-
Save alastairmccormack/e115140ddb1b522059d677f6dbf38f34 to your computer and use it in GitHub Desktop.
Luhn checkbit creator for text strings - Made Python3 compatible from https://wiki.openmrs.org/display/docs/Check+Digit+Algorithm
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
# 99.99 based on https://wiki.openmrs.org/display/docs/Check+Digit+Algorithm | |
def get_checkdigit(id_without_check): | |
# allowable characters within identifier | |
valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVYWXZ_" | |
# remove leading or trailing whitespace, convert to uppercase | |
id_without_checkdigit = id_without_check.strip().upper() | |
# this will be a running total | |
sum = 0; | |
# loop through digits from right to left | |
for n, char in enumerate(reversed(id_without_checkdigit)): | |
if not valid_chars.count(char): | |
raise Exception('InvalidIDException') | |
# our "digit" is calculated using ASCII value - 48 | |
digit = ord(char) - 48 | |
# weight will be the current digit's contribution to | |
# the running total | |
weight = None | |
if (n % 2 == 0): | |
# for alternating digits starting with the rightmost, we | |
# use our formula this is the same as multiplying x 2 and | |
# adding digits together for values 0 to 9. Using the | |
# following formula allows us to gracefully calculate a | |
# weight for non-numeric "digits" as well (from their | |
# ASCII value - 48). | |
## Use_sparingly: In Python 3, '/' makes floats. '//' fixes it for Python 3. | |
## For cross compatibility, simply int() the result | |
## VVVVVVVVVVVVV | |
weight = (2 * digit) - int(digit / 5) * 9 | |
else: | |
# even-positioned digits just contribute their ascii | |
# value minus 48 | |
weight = digit | |
# keep a running total of weights | |
## Use_sparingly: removed maths.fabs() | |
## abs() is sufficient | |
sum += weight | |
# avoid sum less than 10 (if characters below "0" allowed, | |
# this could happen) | |
sum = abs(sum) + 10 | |
# check digit is amount needed to reach next number | |
# divisible by ten. Return an integer | |
return int((10 - (sum % 10)) % 10) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment