Skip to content

Instantly share code, notes, and snippets.

@alastairmccormack
Created November 14, 2016 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alastairmccormack/e115140ddb1b522059d677f6dbf38f34 to your computer and use it in GitHub Desktop.
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
# 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