Python 卢恩公式的实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21079439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:00:18  来源:igfitidea点击:

Implementation of Luhn Formula

pythonmathchecksumluhn

提问by JChris

I was trying to implement the Luhn Formulain Python, here is my code:

我试图在 Python 中实现Luhn 公式,这是我的代码:

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)

  1. 去掉数字的最后一位。最后一位是我们要检查的数字 反转数字

  2. 将奇数位置(1、3、5 等)中的数字乘以 2,然后将所有大于 9 的结果减去 9

  3. 将所有数字相加

  4. 校验位(卡的最后一个数字)是您需要添加的金额才能得到 10 的倍数(模 10)

采纳答案by phyrox

I think the algorithm is not correct.

我认为算法不正确。

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

第二个步骤,你需要总结的产品,而不是9。减去参考的数字:维基百科

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

回答by Guy Gavriely

see this Python recipe

看到这个Python 食谱

def cardLuhnChecksumIsValid(card_number):
    """ checks to make sure that the card passes a luhn mod-10 checksum """

    sum = 0
    num_digits = len(card_number)
    oddeven = num_digits & 1

    for count in range(0, num_digits):
        digit = int(card_number[count])

        if not (( count & 1 ) ^ oddeven ):
            digit = digit * 2
        if digit > 9:
            digit = digit - 9

        sum = sum + digit

    return ( (sum % 10) == 0 )

回答by alko

There are some errors in your code:

您的代码中有一些错误:

result = divmod(sum_of_digits, 10)

returns a tuple, you need only modulo, that is use

返回一个元组,你只需要取模,即使用

result = sum_of_digits % 10

Second, to check for validity, you don't omit last digit (that is checksum), but include it in computations. Use

其次,要检查有效性,不要省略最后一位数字(即校验和),而是将其包含在计算中。用

reverse_sequence = list(int(d) for d in str(int(number[::-1]))) 

And check for result being zero:

并检查结果为零:

if not result:
    print("[VALID] %s" % number)

Or if you insist on keeping this not needed complexity, check for last digit to be inverseof checksum modulo 10: keep

或者,如果您坚持保持这种不需要的复杂性,请检查最后一位数字是否 与校验和模 10取反:保持

reverse_sequence = list(int(d) for d in str(int(number[-2::-1])))

but use

但使用

if (result + last_digit) % 10 == 0:
    print("[VALID] %s" % number)

For a simplier and shorter code, I can give you a reference to my older answer.

对于更简单和更短的代码,我可以给你参考我的旧答案

回答by Sébastien Wieckowski

The following might help some people to start with the Luhn algorithm in python.

以下内容可能会帮助一些人开始使用 Python 中的 Luhn 算法。

num = list(input("Please enter the number to test (no space, no symbols, only \
numbers): "))

num = list(map(int, num))[::-1] #let's transform string into int and reverse it

for index in range(1,len(num),2):
    if num[index]<5:
        num[index] = num[index] *2
    else: #doubling number>=5 will give a 2 digit number
        num[index] = ((num[index]*2)//10) + ((num[index]*2)%10)

checksum=sum(num)

print("checksum= {}".format(checksum))

if checksum%10 !=0:
    print('the number is not valid')
else:
    print('the number is valid!')

回答by Hymantrader

I'd keep it simple and easy to read, something like this:

我会保持简单易读,如下所示:

def luhn(value):
    digits = list(map(int,str(value))
    oddSum = sum(digits[-1::-2])
    evnSum = sum([sum(divmod(2 * d, 10)) for d in digits[-2::-2]])
    return (oddSum + evnSum) % 10 == 0

But there's tons of ways to do the same thing. Obviously, you'd have to do it differently to see the actual output, this just sums up the total to determine if the value is valid.

但是有很多方法可以做同样的事情。显然,您必须以不同的方式查看实际输出,这只是总结总数以确定该值是否有效。

Best!

最好的事物!

回答by Andreina

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

这是我发现的 Luhn 测试最简洁的 Python 公式:

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.

上述函数和其他 Luhn 实现(以不同的编程语言)可在https://www.rosettacode.org/wiki/Luhn_test_of_credit_card_numbers 中找到

回答by Chadwick

check_numbers = ['49927398716', '4847352989263095', '79927398713', '5543352315777720']

def Luhn_Check(number):
    """
        this function checks a number by using the Luhn algorithm.

        Notes (aka - How to Luhn) :
            Luhn algorithm works in a 1 2 1 2 ... order.
            Therefore, in computer speak, 1 0 1 0 ... order

            step 1:
                -> reverse the # so we are not working from right to left (unless you want too)
                -> double every second number

            step 2:
                -> if the doubled number is greater then 9, add the individual digits of the number to get a single digit number
                    (eg. 12, 1 + 2 = 3)

            step 3:
               -> sum all the digits, if the total modulo is equal to 0 (or ends in zero) then the number is valid...
    """

    reverse_numbers = [int(x) for x in number[::-1]] # convert args to int, reverse the numbers, put into a list
    dbl_digits = list() # create empty list
    digits = list(enumerate(reverse_numbers, start=1)) # enumerate numbers starting with an index of 1

    for index, digit in digits:
        if index % 2 == 0:  # double every second (other) digit.

            doub_digit = digit * 2
            dbl_digits.append(doub_digit - 9) if doub_digit > 9 else dbl_digits.append(doub_digit)

        else:
            # if not '0' append to list (this would be the 1 in Luhn algo sequence (1 2 1 2 ...)
            dbl_digits.append(digit)

    return sum(dbl_digits) % 10


if (__name__ == "__main__"):
    print("Valid Numbers: %s " % [x for x in check_numbers if Luhn_Check(x) == 0])