CS50 Luhn算法问题:无效Visa卡号被误判为有效Visa
问题分析与修复方案
你的程序把无效卡号(4111111111111113、4222222222223)错误识别为Visa的核心问题出在循环条件错误,同时Luhn算法的逻辑也存在偏差,具体说明如下:
1. 循环条件完全写反
你写的for循环条件是number < 0,但输入的卡号是正整数,number初始值等于输入的卡号,永远不可能小于0,导致循环一次都没执行。此时sum始终为0,而0 % 10 == 0会让isValid被错误设为true——只要卡号开头是4且长度符合Visa的13/16位要求,就会被判定为Visa,完全跳过了Luhn算法的有效性验证。
2. Luhn算法逻辑错误
即使循环能执行,当前逻辑也不符合Luhn规则:你每次循环先把当前位数字加到sum,然后当i%2==0时又把同一个数字乘以2再加一遍,这会导致重复计算,且处理的位置也不对。正确的Luhn算法应该是从右往左数,第2、4、6...位(偶数位)乘以2,再把乘积的各位数字相加,第1、3、5...位(奇数位)直接相加。
修正后的代码
#include <cs50.h> #include <stdio.h> #include <math.h> int main(void) { string cardType = "VALID"; long card = get_long("Number: "); int length = floor(log10(card)) + 1; bool isValid = false; long number = card; long startNumber = card; int productNumber; int sum = 0; int position = 0; // 记录当前是从右数第几位 // 获取前两位数字 while (startNumber > 100) { startNumber /= 10; } // 正确遍历卡号每一位,执行Luhn算法 while (number > 0) { int digit = number % 10; position++; if (position % 2 == 0) { // 偶数位(从右数)乘以2,拆分各位相加 productNumber = digit * 2; sum += (productNumber % 10) + (productNumber / 10); } else { // 奇数位直接相加 sum += digit; } number /= 10; } isValid = (sum % 10 == 0); // 判断卡类型 if (length == 15 && isValid && (startNumber == 34 || startNumber == 37)) { cardType = "AMEX"; } else if (length == 16 && isValid && (startNumber >= 51 && startNumber <= 55)) { cardType = "MASTERCARD"; } else if ((length == 13 || length == 16) && isValid && (startNumber >= 40 && startNumber < 50)) { cardType = "VISA"; } else { cardType = "INVALID"; } printf("%s\n", cardType); }
额外优化点
- 把
for循环改成while循环更直观,用position变量记录从右数的位数,避免索引混淆 - 简化
isValid的赋值逻辑,直接写成isValid = (sum % 10 == 0) - MasterCard的判断简化为
startNumber >=51 && startNumber <=55,无需逐个枚举数字
内容的提问来源于stack exchange,提问作者Mennatalla Khougha
相关产品推荐
相关产品推荐

