Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementation of Luhn Formula

I was trying to implement the Luhn Formula in Python. Here is my code:

import sys


def luhn_check(number):
    if number.isdigit():
        last_digit = int(str(number)[-1])
        reverse_sequence = list(int(d) for d in str(int(number[-2::-1])))

        for i in range(0, len(reverse_sequence), 2):
            reverse_sequence[i] *= 2

        for i in range(len(reverse_sequence)):
            if reverse_sequence[i] > 9:
                reverse_sequence[i] -= 9

        sum_of_digits = 0
        for i in range(len(reverse_sequence)):
            sum_of_digits += reverse_sequence[i]

        result = divmod(sum_of_digits, 10)

        if result == last_digit:
            print("[VALID] %s" % number)
        else:
            print("[INVALID] %s" % number)
        quit()

    print("[ERROR] \" %s \" is not a valid sequence." % number)
    quit()


def main():
    if len(sys.argv) < 2:
        print("Usage: python TLF.py <sequence>")
        quit()

    luhn_check(sys.argv[1])

if __name__ == '__main__':
    main()

But it isn't working properly:

[INVALID] 4532015112830366
[INVALID] 6011514433546201
[INVALID] 6771549495586802

and so on...

But the logic of the code seems OK to me. I followed this workflow:

The Luhn Formula

  1. Drop the last digit from the number. The last digit is what we want to check against Reverse the numbers

  2. Multiply the digits in odd positions (1, 3, 5, etc.) by 2 and subtract 9 to all any result higher than 9

  3. Add all the numbers together

  4. The check digit (the last number of the card) is the amount that you would need to add to get a multiple of 10 (Modulo 10)

like image 691
JChris Avatar asked Jan 12 '14 19:01

JChris


2 Answers

I think the algorithm is not correct.

The second step you need to sum the digits of the products instead of substract 9. Reference: Wikipedia.

In the Wikipedia you have this example:

def luhn_checksum(card_number):
    def digits_of(n):
        return [int(d) for d in str(n)]
    digits = digits_of(card_number)
    odd_digits = digits[-1::-2]
    even_digits = digits[-2::-2]
    checksum = 0
    checksum += sum(odd_digits)
    for d in even_digits:
        checksum += sum(digits_of(d*2))
    return checksum % 10

def is_luhn_valid(card_number):
    return luhn_checksum(card_number) == 0


result = is_luhn_valid(4532015112830366)
print 'Correct:' + str(result)
result = is_luhn_valid(6011514433546201)
print 'Correct:' + str(result)
result = is_luhn_valid(6771549495586802)
print 'Correct:' + str(result)

Result:

>>>Correct:True
>>>Correct:True
>>>Correct:True
like image 75
phyrox Avatar answered Sep 24 '22 06:09

phyrox


This is the most concise python formula for the Luhn test I have found:

def luhn(n):
    r = [int(ch) for ch in str(n)][::-1]
    return (sum(r[0::2]) + sum(sum(divmod(d*2,10)) for d in r[1::2])) % 10 == 0

The above function and other Luhn implementations (in different programming languages) are available in https://www.rosettacode.org/wiki/Luhn_test_of_credit_card_numbers .

like image 22
Andreina Avatar answered Sep 26 '22 06:09

Andreina