首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Luhn算法

Python Luhn算法
EN

Stack Overflow用户
提问于 2021-03-13 02:22:15
回答 3查看 84关注 0票数 0

现在,当我运行这段代码时,我得到一个错误提示"4不在列表中“,因为if (numberList.index(digit)-1) % 2 == 0:行不确定我哪里出错了,但如果有任何提示我们将不胜感激。它从倒数第二个字母开始,if语句通过.index(digit) % 2 == 0检查它是否每隔一个字母

代码语言:javascript
复制
def credit():
      cardType = ""
      mastercard = ["51", "52", "53", "54", "55"]
      american_express = ["34", "37"]
      total = 0
      while True:
            number = input("Enter Valid Credit Card Number: ")
            if " " in str(number):
                  print("INVALID")
                  continue
            number = int(number)
            if len(str(number)) == 15 and str(number)[0:2] in american_express:
                  cardType = "American Express"
                  break
            elif len(str(number)) == 16:
                  if str(number)[0] == "4":
                        cardType = "Visa"
                  elif str(number)[0:2] in mastercard:
                        cardType = "Mastercard"
                  break
            elif len(str(number)) == 13:
                  cardType = "Visa"
                  break
            else:
                  print("INVALID CARD")
                  continue

      numberList = []
      for n in str(number):
            numberList.append(n)

      for digit in numberList[::-2]:
            digit = int(digit)
            if numberList.index(digit) % 2 == 0:
                  if (digit*2) >= 10:
                        total += ((digit*2) / 10)
                        total += ((digit*2) % 10)
                  elif (digit*2) < 10:
                        total += digit
            else:
                  if digit > 10:
                        total += (digit / 10)
                        total += (digit % 10)
                  elif digit < 9:
                        total += digit
      if (total % 10) == 0:
            print(cardType)
      else:
            print("INVALID CARD")
      print(total)
      
credit()
EN

回答 3

Stack Overflow用户

发布于 2021-03-13 02:34:16

这是因为您已将该字符转换为int:

代码语言:javascript
复制
      for digit in numberList[::-2]:
            digit = int(digit)
            if numberList.index(digit) % 2 == 0:

numberList是单个字符的列表。但是字符不同于整数:"9" != 9,所以index找不到这个整数。

因此,要么执行numberList.index(str(digit)),要么将语句digit = int(digit)推迟到执行完if条件之后。然后,您需要将该语句放入ifelse块中。

您可以通过将numberList设置为整数(而不是字符)列表来完全避免这种情况:

替换为:

代码语言:javascript
复制
      numberList = []
      for n in str(number):
            numberList.append(n)

通过以下方式:

代码语言:javascript
复制
      numberList = list(map(int, s))

现在,您不需要语句digit = int(digit)

票数 0
EN

Stack Overflow用户

发布于 2021-03-13 03:29:04

@trincot指出了一个索引错误。另一种是numberList.index(str(digit))将返回匹配的第一个数字的索引,例如,如果它们是两个4,那么它将为这两个数字提供相同的索引。

下面是一个有效的算法:

代码语言:javascript
复制
def card_type(number):
    cardType = ""
    mastercard = '51','52','53','54','55'
    american_express = '34','37'
    digits = len(number)
    if digits == 15 and number[:2] in american_express:
        return 'American Express'
    elif digits == 16 and number[0] == '4' or digits == 13:
        return 'Visa'
    elif number[:2] in mastercard:
        return 'Mastercard'
    else:
        return 'Unknown'

def credit(number):
      # https://en.wikipedia.org/wiki/Luhn_algorithm
      total = 0
      for digit in number[-2::-2]: # every other digit from right starting 2nd-to-last
          value = int(digit) * 2
          total += value if value < 10 else value - 9 # value-9 same as sum of two digits, e.g. 16 => 1+6 = 16-9 = 7
      for digit in number[-1::-2]: # every other digit from right starting from last
          total += int(digit)
      if total % 10 == 0:
          return card_type(number)
      return 'Invalid'

print(credit('4123456789123450')) # Visa
print(credit('341234567891232'))  # AmEx
print(credit('5112345678912349')) # Mastercard
print(credit('1234567891233'))    # Visa
print(credit('123'))              # bad check
print(credit('125'))              # valid but unrecognized
代码语言:javascript
复制
Visa
American Express
Mastercard
Visa
Invalid
Unknown
票数 0
EN

Stack Overflow用户

发布于 2021-03-13 03:48:46

你的for digit in numberList[::-2]:只处理每隔一个数字,完全跳过中间的数字。然后,假设您正在遍历所有数字,您将找到一个数字在字符串中的位置,如果代码中有重复的数字,该位置将不会给出正确的值。除此之外,即使代码中没有重复的数字,.index()也会从开头查找位置,因此如果代码中有偶数个位置,您所做的奇/偶测试将给出错误的答案。

要正确执行Luhn测试,必须在开始之前反转代码。然后,一切都变得更简单,可以按顺序执行(例如,使用总和和理解)。

例如:

代码语言:javascript
复制
def luhnTest(code):
    digits = [*map(int,code[::-1])]
    cd = sum(digits) + sum(d - (d>4)*9 for d in digits[1::2])
    return not cd % 10   

将每个数字(包括校验位)相加一次,以验证校验位。奇数位置的数字(在反码中)被再次相加(即,加倍),但是,如果加倍> 10,则将加倍的值的数字相加,这相当于减去9(即- (d>4)*9)。

代码语言:javascript
复制
# test set from https://en.wikipedia.org/wiki/Luhn_algorithm
tests = [79927398710, 79927398711, 79927398712, 79927398713, 79927398714,
         79927398715, 79927398716, 79927398717, 79927398718, 7992739871]

for t in tests: print(t,luhnTest(str(t)) 

79927398710 False
79927398711 False
79927398712 False
79927398713 True
79927398714 False
79927398715 False
79927398716 False
79927398717 False
79927398718 False
7992739871 False

只需稍加修改,您就可以将其分解为一个单独的理解:

代码语言:javascript
复制
return 1>sum(d+(i%2)*(d-(d>4)*9) for i,d in enumerate(map(int,code[::-1])))%10
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66605252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档