我正在尝试用 C 语言实现 Luhn 算法来检查信用卡有效性,对于那些不知道的人......就是这样:
\n从数字\xe2\x80\x99s\n倒数第二个数字开始,每隔一个数字乘以 2,然后将这些乘积\xe2\x80\x99 数字相加。
\n将总和添加到 \xe2\x80\x99t 乘以 2 的数字之和。
\n如果总计 \xe2\x80\x99s 最后一位数字为 0(或者,更正式地说,如果总计
\n模 10 与 0 全等),则该数字有效!
为了实现这一点,我循环遍历整个数字,如果我所在的数字位置的模 2 等于 0,那么我将乘以 2 并添加到一个名为totalEven
。
如果不是这种情况,我会将我所在的号码添加到totalOdd
而不进行乘法。
然后我会将这个位置加 1,并检查其他数字,直到达到 16(卡片的最大数字)。
\n我稍后会将这两个变量相加,并检查总模数 10 是否等于 0。如果这意味着信用卡号是正确的,否则就是错误的。
\n这是代码:
\n#include <stdio.h>\n#include <cs50.h>\n\n//list of variables\n\n //is the card valid\n bool isValid = true;\n // the creditcard number\n long input;\n //mod stands for modules, and is used to single out each number as seen later\n int mod = 10;\n //the location at which number I am checking\n int place = 1;\n //num is the number I am checking that has been singled out\n int num = 0;\n //total of numbers * 2 located at locations numbered with even numbers\n int totalEven = 0;\n //total of numbers located at locations numbered with odd numbers\n int totalOdd = 0;\n
Run Code Online (Sandbox Code Playgroud)\n //gets input and stores it in well.. input\n input = get_long("Number: ");\n \n // a formula to single out a number, starting with the ones and then as you can see, mod is muliplied by 10 to go over the second number.\n\n num = ((input % mod) - (input % (mod /10))) / (mod/10);\n \n //loops 16 times\n for(int i = 0; i < 16; i++)\n {\n // if the place is even execute below\n if(place % 2 == 0)\n {\n totalEven = totalEven + num * 2;\n } \n //else do this\n else if (place % 2 != 0)\n {\n totalOdd = totalOdd + num; \n }\n //moves to the next number\n mod = mod * 10;\n place++;\n }\n \n //fufils the last step of the algorithm\n\n if((totalEven + totalOdd) % 10 == 0 )\n {\n isValid = true;\n }\n else\n {\n isValid = false;\n }\n
Run Code Online (Sandbox Code Playgroud)\n问题是这段代码给了我无效或!isValid
即使信用卡号应该是正确的,我检查了我的“公式”,它工作得很好......
我完全不知道该怎么办...我是一个谦虚的爱好者,所以请不要因为上面的怪物而烤我。
\n这是代码的完整版本
\n#include <stdio.h>\n#include <cs50.h>\n\n\nlong power();\n\n\nint main(void)\n{\n //AMERX 15 STRT 34 OR 37\n //MC 16 STRT 51, 52, 53, 54, 55\n //VZA 13 OR 16 STRT 4\n\n long input;\n bool isValid = true;\n string type;\n int mod = 10;\n int place = 1;\n int num = 0;\n int totalEven = 0;\n int totalOdd = 0;\n\n do\n {\n input = get_long("Number: ");\n \n\n }\n\n while(input < 0);\n \n \n for(int i = 0; i < 16; i++)\n {\n num = ((input % mod) - (input % (mod /10))) / (mod/10);\n if(place % 2 == 0)\n {\n totalEven = totalEven + num * 2;\n }\n else\n {\n totalOdd = totalOdd + num; \n }\n \n mod = mod * 10;\n place++;\n }\n \n if((totalEven + totalOdd) % 10 == 0 )\n {\n isValid = true;\n }\n else\n {\n isValid = false;\n \n printf("%i , %i", totalEven, totalOdd);\n }\n if (isValid == true){\n if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13)))) \n {\n type = "AMEX\\n";\n }\n else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))\n {\n type = "MASTERCARD\\n";\n }\n else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))\n {\n type = "VISA\\n";\n } \n else{\n type = "error\\n";\n }\n}\n else\n {\n type = "INVALID\\n";\n }\n \n\n if((totalEven + totalOdd) % 10 == 0 )\n {\n isValid = true;\n }\n else\n {\n isValid = false;\n }\n \n printf("%s", type);\n\n}\n\n\n\n\n\nlong power(int n, int p)\n{\n long result = 1;\n for(int i = 0; i<p; i++)\n {\n result = result * n;\n }\n return result;\n\n
Run Code Online (Sandbox Code Playgroud)\n
我不是 Luhn 算法的专家,但当我阅读 https://en.wikipedia.org/wiki/Luhn_algorithm时,我觉得你做错了。
\n引用自https://en.wikipedia.org/wiki/Luhn_algorithm:
\n\n\n从最右边的数字(不包括校验位)开始向左移动,每隔两个数字的值加倍。校验位既不加倍也不包含在该计算中;第一个加倍的数字是紧邻校验位左侧的数字。如果此加倍运算的结果大于 9(例如,8 \xc3\x97 2 = 16),则将结果的数字相加(例如,16: 1 + 6 = 7, 18: 1 + 8 = 9)或者,也可以通过从结果中减去 9 得到相同的最终结果(例如,16: 16 \xe2\x88\x92 9 = 7、18: 18 \xe2\x88\x92 9 = 9)。
\n
我在您的代码中没有看到处理粗体部分的任何地方。
\n代替
\ntotalEven = totalEven + num * 2;\n
Run Code Online (Sandbox Code Playgroud)\n我想你需要
\nint tmp = num * 2;\nif (tmp > 9) tmp = tmp - 9;\ntotalEven = totalEven + tmp;\n
Run Code Online (Sandbox Code Playgroud)\n也就是说 - 我认为通过将输入存储为数字,您使实现比所需的复杂得多。您可以使用数字数组来代替数字。
\n那就是 - 而不是
\nlong input = 1122334455667788\n
Run Code Online (Sandbox Code Playgroud)\n使用
\nint digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};\n// Notice that index zero is the rightmost digit\n
Run Code Online (Sandbox Code Playgroud)\n这样算法就简单多了:
\n// Double every second element and check for overflow\nfor (idx = 1; idx < 16; idx += 2)\n{\n digits[idx] = 2 * digits[idx];\n if (digits[idx] > 9) digits[idx] = digits[idx] - 9;\n}\n\n// Calculate the sum\nsum = 0;\nfor (idx = 0; idx < 16; ++idx)\n{\n sum = sum + digits[idx];\n}\n
Run Code Online (Sandbox Code Playgroud)\n如果您必须接收数字形式的输入,请首先调用将数字转换为数字数组的函数。您可以在 SO 上找到很多很多如何完成转换的示例。这里将整数转换为数字数组只是众多示例之一。
\n