Welcome, guest | Sign In | My Account | Store | Cart

Test validity of any credit card number using the LUHN method (mod 10). Starting at the last digit and moving backwards, you add up every other digit. Then, you double the left-out digits, and add the digits of these results to the original sum. If this satisfies sum mod 10 == 0 then the card is valid.

This is also explained at http://www.beachnet.com/~hstiles/cardtype.html

Python, 18 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import re
def validate(number):
    'Validates any credit card number using LUHN method'
    number = str(number)
    re.sub(r' ', '', number)
    count = 0
    for i in range(len(number)):
        val = int(number[-(i+1)])
        if i % 2 == 0:
            count += val
        else:
            count += int(str(2 * val)[0])
            if val > 5:
                count += int(str(2 * val)[1])
    if count % 10 == 0:
        return True
    else:
        return False

2 comments

Rogier Steehouder 12 years, 8 months ago  # | flag

Some constructive criticism:

re.sub() returns the altered string. You have to assign it to a variable.

Do not use regular expressions where str.replace() works fine:

number = number.replace(' ', '')

Don't do math with strings. Floor division (//) and remainder (%) work well for this.

Have a look at list comprehensions.

My version:

def validate(number):
    # each digit in number as an int in reverse order
    numlist = [int(c) for c in reversed(str(number)) if c.isdigit()]
    count = 0
    # automatic numbering
    for i, val in enumerate(numlist):
        if i % 2 == 0:
            count += val
        else:
            # first digit of the double value
            count += (2 * val) // 10
            # last digit of the double value
            count += (2 * val) % 10
    # no need for an if statement
    return (count % 10 == 0)

or even:

def validate(number):
    numlist = [int(x) for x in reversed(str(number)) if x.isdigit()]
    # digits that count once
    count = sum(x for i, x in enumerate(numlist) if i % 2 == 0)
    # digits that count double (add digits of double value)
    count += sum(sum(divmod(2 * x, 10)) for i, x in enumerate(numlist) if i % 2 != 0)
    return (count % 10 == 0)
Shawn Zhang 12 years, 3 months ago  # | flag

I've practise a more short version with credit card number in string :

def validation_creditcard(string_number):
    list_doubled = [ int(x)*2 for n,x in enumerate(string_number[::-1]) if n%2 != 0 ]
    list_A = reduce(lambda x,y: x+y,map(lambda x:list(str(x)), list_doubled))
    list_B = [x for n,x in enumerate( string_number[::-1] ) if n%2 == 0 ]
    return reduce(lambda x,y:int(x)+int(y), list_A+list_B) % 10 == 0