The Luhn algorithm or Luhn formula was created by IBM scientist Hans
Peter Luhn. It is a simple check digit formula used to validate a
variety of identification numbers, such as credit card numbers. The
scheme allows a computer to quickly check for errors when a human is
entering the number. Many credit card numbers and many government
identification numbers use the algorithm as a simple method of
distinguishing valid numbers from mistyped or otherwise incorrect
numbers.
It works as follows: One digit (usually the least significant or
rightmost digit) in the number is treated as the check digit.
The other digits, called the payload are used to re-compute the
check digit using a simple arithmetic computation. The computed value
is then compared to the check digit. If the two match, it is assumed
that the number is correct. If some digit was mis-typed or two digits
were transposed, the check will probably fail. The algorithm was
designed to protect against accidental errors, not malicious attacks,
as it's not hard to defeat.
Here are the steps of the algorithm:
Start with the number to check:
dn...d2d1d0.
Remove and save the check digit d0 from the number. This leaves the
payload: dn...d2d1
Double every digit with an odd number subscript. If a doubled
digit exceeds 9, subtract 9 from the result. For example, if the
digit is 6, double it to get 12, and then subtract 9 to get 3
as the result for that digit.
Sum all of the resulting digits (including those that were
doubled). Call this s.
The check digit is calculated as (( 10 - ( s mod 10 ) ) mod 10). Recall
that mod is the "%" operator.
Compare the computed check digit with the stored check digit
d0. If they match, accept the number as correct.
Otherwise, reject the number.
Note: In the picture at the top, they've reversed the order of
the digits.
Your Assignment:
For this assignment, you'll implement a simplified version of the Luhn
Algorithm. Your version need only deal with 7-digit numbers, where
the least significant (rightmost) digit is assumed to be the stored
check digit. (To do Luhn in generality for arbitrary sized number,
you'd need loops, which we haven't covered yet.) Perform the following
steps:
Using an input() statement, accept from the user an integer n.
Validate that n is non-negative and less than 107. If
not, print an error message and stop.
Extract the digits and print them as you go; see the samples
below. Do this arithmetically; don't convert the number to a
string. Print each digit and the rest of the number after
that digit is removed.
Compute the expected check value from the payload: d6...d2d1.
Compare it to the stored check digit d0.
If they agree, print a message saying so. (See the samples
below.)
If they disagree, print a message saying so, and what the digit
should be (the check value you computed).
Note that n can have fewer than 7 digits; if so, assume that
it's padded on the left with 0's. Your code shouldn't have to check that.
Extracting the Digits
How do you go about extracting the 7 digits from n? Recall
that if you have a number n, then n % 10 is the
remainder when you divide by 10. For a decimal number, that's just
the least significant digit. Also, n // 10 is what remains
after you drop the least significant digit. E.g., to get digits
d0 and d1 from a k-digit number n, you could do the
following:
d0 = n % 10 # extract d0
r = n // 10 # digits [k-1..1]
d1 = r % 10 # digit d1
r = r // 10 # digits [k-1..2]
To extract the other digits, just continue in the same
way. Note: we could do this in a loop to extract all of the
digits into a list, but we haven't yet covered loops or lists. So
don't do that, even if you know how.
Sample Output
> python Luhn.py
Enter a non-negative 7-digit integer: 87654321
Illegal number entered.
> python Luhn.py
Enter a non-negative 7-digit integer: -1234567
Illegal number entered.
> python Luhn.py
Enter a non-negative 7-digit integer: 7654321
d0:1; r:765432
d1:2; r:76543
d2:3; r:7654
d3:4; r:765
d4:5; r:76
d5:6; r:7
d6:7; r:0
Number is invalid: 7654321
Check digit should be: 0
> python Luhn.py
Enter a non-negative 7-digit integer: 7654320
d0:0; r:765432
d1:2; r:76543
d2:3; r:7654
d3:4; r:765
d4:5; r:76
d5:6; r:7
d6:7; r:0
Number is valid: 7654320
> python Luhn.py
Enter a non-negative 7-digit integer: 4321
d0:1; r:432
d1:2; r:43
d2:3; r:4
d3:4; r:0
d4:0; r:0
d5:0; r:0
d6:0; r:0
Number is invalid: 4321
Check digit should be: 5
> python Luhn.py
Enter a non-negative 7-digit integer: 4325
d0:5; r:432
d1:2; r:43
d2:3; r:4
d3:4; r:0
d4:0; r:0
d5:0; r:0
d6:0; r:0
Number is valid: 4325
>
Turning in the Assignment:
The program should be in a file named Luhn.py. Submit
the file via Canvas before the deadline shown at the top of this page.
Submit it to the assignment hw4 under the assignments
sections by uploading your Python file.
Be sure to test your program before submission. It must also contain a
header with the following format:
If you submit multiple times to Canvas, it will rename your file name
to something like Luhn-1.py, Luhn-2.py, etc.
Don't worry about that; we'll grade the latest version.
Programming tips
You can assume. When an assignment says that "you can assume"
something about the input, that just means that you don't have to
check it. If the user enters an input that doesn't meet that
assumption, the program can crash or behave badly. That's not your
problem.
For many of the assignments this semester, we'll say that you can
assume certain things about the inputs, often because you don't yet
have the skills necessary to check for certain errors. But if you get
a programming job, you should always validate the inputs as much as
possible. In general, it's bad programming practice to allow bad
inputs to crash your program; it means that your program is not
robust. Later we'll insist that you "validate" some inputs, meaning to
assure that they do meet specifications.