手动运行正常但while循环失效:Luhn算法卡号生成问题
问题:自动生成符合Luhn算法的有效信用卡号失败
我编写了以下Python代码,用来生成符合Luhn算法的信用卡号、有效期及CVV并写入CSV文件。手动运行时偶尔能得到有效卡号,但把校验逻辑放进while循环后,程序一直返回“Not valid”。我需要实现程序自动生成有效卡号,不用手动重复运行。
import random def ranCardNum(): ranCardNumls = [] for i in range(0,16): ranNum = random.randint(0,9) ranCardNumls.append(ranNum) return ranCardNumls #Gets random 16 digits long number and adds it to a list def luhnAlgo(NoPrPro): #print("".join(str(n) for n in NoPrPro)) for i in range(14,0,-2): NoPrPro[i] = NoPrPro[i] * 2 if NoPrPro[i] >= 10: first = str(NoPrPro[i])[0] second = str(NoPrPro[i])[1] NoPrPri= int(first) + int(second) NoPrPro[i] = NoPrPri return "".join(str(n) for n in NoPrPro) #The luhn algorithm returns number without the list def endDate(): dateM = random.randint(1,12) if dateM <= 9: letter = str(dateM) dateM = "0" + letter dateY = random.randint(2022,2026) return dateM, dateY #generates random dates and returns them def ranCvv(): ranCvv = random.randint(100,1000) return ranCvv #random 3 digit number and returns it def writeCsv(cardNum,cardDay, cardYear, cvv): f = open("cardNo.csv","a") f.write(cardNum + ",") f.write(cardDay + ",") f.write(cardYear + ",") f.write(cvv + "\r") f.close() #writes to my csv file #Check - Taken from geeksforgeeks.org def checkLuhn(cardNo): nDigits = len(cardNo) nSum = 0 isSecond = False for i in range(nDigits - 1, -1, -1): d = ord(cardNo[i]) - ord('0') if (isSecond == True): d = d * 2 nSum += d // 10 nSum += d % 10 isSecond = not isSecond if (nSum % 10 == 0): return True else: return False cardNo = luhnAlgo(ranCardNum()) if __name__=="__main__": if (checkLuhn(cardNo)): print(cardNo) expDay = str(endDate()[0]) expYear = str(endDate()[1]) cvv = str(ranCvv()) writeCsv(cardNo, expDay,expYear, cvv) else: print("Not valid")
问题原因
你的luhnAlgo函数没有正确实现Luhn算法的生成逻辑——它只是对随机生成的16位数字中的部分位做了加倍拆分,但没有计算并设置校验位,导致生成的卡号几乎都不符合Luhn规则,手动运行成功只是极小概率的巧合。
解决方案
正确的Luhn卡号生成逻辑是:先生成前15位随机数字,再通过算法计算出第16位校验位,这样生成的卡号必然符合规则,无需循环重试。修改后的代码如下:
import random def generate_valid_card_number(): # 生成前15位随机数字 prefix = [random.randint(0,9) for _ in range(15)] total = 0 is_second = False # 按Luhn规则计算前15位的总和 for digit in reversed(prefix): if is_second: digit *= 2 total += digit // 10 + digit % 10 else: total += digit is_second = not is_second # 计算校验位:让总和成为10的倍数 check_digit = (10 - (total % 10)) % 10 prefix.append(check_digit) return ''.join(map(str, prefix)) def endDate(): dateM = random.randint(1,12) dateM = f"0{dateM}" if dateM <=9 else str(dateM) dateY = str(random.randint(2022,2026)) return dateM, dateY def ranCvv(): return str(random.randint(100,999)) def writeCsv(cardNum, cardDay, cardYear, cvv): with open("cardNo.csv","a", encoding='utf-8') as f: f.write(f"{cardNum},{cardDay},{cardYear},{cvv}\n") # 保留原校验函数用于验证(可选) def checkLuhn(cardNo): nDigits = len(cardNo) nSum = 0 isSecond = False for i in range(nDigits - 1, -1, -1): d = ord(cardNo[i]) - ord('0') if isSecond: d *= 2 nSum += d // 10 nSum += d % 10 isSecond = not isSecond return nSum % 10 == 0 if __name__=="__main__": cardNo = generate_valid_card_number() # 验证生成的卡号(可选步骤) if checkLuhn(cardNo): print(f"生成有效卡号:{cardNo}") expDay, expYear = endDate() cvv = ranCvv() writeCsv(cardNo, expDay, expYear, cvv) else: print("生成失败")
关键修改点
- 新增
generate_valid_card_number函数,严格按照Luhn算法生成有效卡号,确保每次生成的卡号都符合校验规则 - 优化
endDate和writeCsv的写法,用f-string简化字符串拼接,writeCsv改用with语句自动管理文件资源,避免泄漏 - 主逻辑直接生成有效卡号,无需循环重试
内容的提问来源于stack exchange,提问作者nially
相关产品推荐
相关产品推荐

