Python信用卡校验函数异常:两个无效卡号误判为VISA
信用卡校验程序BUG修复方案
你的代码存在三个核心问题,导致4111111111111113和4222222222223这两个卡号校验错误:
问题1:Luhn算法的数字处理方向错误
Luhn算法要求从卡号最右侧(最后一位)开始向左遍历,每隔一位(倒数第2、4、6...位)乘2,但你的odd_sum和even_sum是从左往右处理的,完全颠倒了计算逻辑,导致求和结果错误,无法正确校验卡号有效性。
问题2:主函数逻辑完全颠倒
当前逻辑是:卡号长度符合要求就直接输出卡类型(跳过Luhn校验),长度不符合才去做Luhn校验。正确逻辑应该是:只有长度符合要求且Luhn校验通过时,才识别卡类型;否则一律输出INVALID。
问题3:辅助函数的返回值与输出格式问题
check_length函数在长度不符合时仅打印INVALID,但未返回False,导致主函数逻辑判断混乱;card_type函数中VISA的输出多了一个多余的换行符,导致输出格式不符合测试要求。
修改后的完整代码
# 实现Luhn算法:从右往左数,每隔一位乘2后的数字和 def luhn_double_sum(num): num_str = str(num) # 从右往左取偶数位置的数字(倒数第2、4...位),转换为int后乘2 double_digits = [int(num_str[i]) * 2 for i in range(len(num_str)-2, -1, -2)] total = 0 for digit in double_digits: # 大于9的数字拆分为个位+十位求和 total += digit // 10 + digit % 10 if digit > 9 else digit return total # 实现Luhn算法:剩余数字的和(从右往左数的奇数位置,即倒数第1、3...位) def luhn_remain_sum(num): num_str = str(num) # 从右往左取奇数位置的数字(倒数第1、3...位) remain_digits = [int(num_str[i]) for i in range(len(num_str)-1, -1, -2)] return sum(remain_digits) # 校验卡号长度是否符合要求 def check_length(num): num_length = len(str(num)) # AMEX是15位,VISA是13/16位,MASTERCARD是16位,所以总长度范围是13-16且包含15 return 13 <= num_length <= 16 # 执行Luhn校验 def luhn_check(num): return (luhn_double_sum(num) + luhn_remain_sum(num)) % 10 == 0 # 识别卡类型 def card_type(card_num): card_str = str(card_num) first_two = card_str[:2] if first_two in ["34", "37"] and len(card_str) == 15: return "AMEX" elif first_two in ["51", "52", "53", "54", "55"] and len(card_str) == 16: return "MASTERCARD" elif card_str[0] == "4" and len(card_str) in [13, 16]: return "VISA" else: return "INVALID" # 主程序 def main(): card_num = input("CARD: ").strip() # 先判断输入是否为纯数字 if not card_num.isdigit(): print("INVALID") return card_num = int(card_num) if check_length(card_num) and luhn_check(card_num): print(card_type(card_num)) else: print("INVALID") if __name__ == "__main__": main()
修改说明
- 重命名了函数,让功能更清晰,严格按照Luhn算法的要求从右往左处理数字;
- 修正了主函数逻辑:只有长度符合且Luhn校验通过,才输出卡类型,否则输出INVALID;
- 给
card_type增加了长度校验(比如AMEX必须是15位,MASTERCARD必须是16位),避免误判; - 增加了输入合法性校验,防止非数字输入导致报错;
- 移除了多余的换行符,保证输出格式符合测试要求。
修改后测试4111111111111113和4222222222223,会正确输出INVALID,其他测试用例也能全部通过。
内容的提问来源于stack exchange,提问作者Alexandru_Ghi
相关产品推荐
相关产品推荐

