尝试在 C 中实现 Luhn 算法
Trying to implement Luhn's Algorithm in C
我正在尝试用C语言实现Luhn的算法来检查信用卡的有效性,对于那些不知道的人......就是这样:
从数字开始,每隔一个数字乘以 2
倒数第二个数字,然后将这些产品的数字相加。
将未乘以 2 的数字的总和相加
如果总数的最后一位是 0(或者,更正式地说,如果总数
模 10 等于 0),该数字有效!
为了实现它,我遍历了整个数字,如果我所在的数字的模数 2 等于 0,那么我将乘以 2 并添加到一个名为 totalEven
的变量中。
如果不是这种情况,我会将我所在的数字添加到 totalOdd
而无需乘法。
然后我会将位置递增 1 并检查其他数字,直到达到 16(卡片的最大位数)。
稍后我会添加两个变量并检查总模十是否等于 0。如果这意味着信用卡号码正确,否则它是错误的。
代码如下:
#include <stdio.h>
#include <cs50.h>
//list of variables
//is the card valid
bool isValid = true;
// the creditcard number
long input;
//mod stands for modules, and is used to single out each number as seen later
int mod = 10;
//the location at which number I am checking
int place = 1;
//num is the number I am checking that has been singled out
int num = 0;
//total of numbers * 2 located at locations numbered with even numbers
int totalEven = 0;
//total of numbers located at locations numbered with odd numbers
int totalOdd = 0;
//gets input and stores it in well.. input
input = get_long("Number: ");
// 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.
num = ((input % mod) - (input % (mod /10))) / (mod/10);
//loops 16 times
for(int i = 0; i < 16; i++)
{
// if the place is even execute below
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
//else do this
else if (place % 2 != 0)
{
totalOdd = totalOdd + num;
}
//moves to the next number
mod = mod * 10;
place++;
}
//fufils the last step of the algorithm
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
问题是这个代码块给我无效或 !isValid
即使信用卡号应该是正确的并且我检查了我的“公式”并且它工作得很好...
我完全不知道该怎么做...我是一个谦虚的爱好者所以请不要因为上面的怪物而烤我。
这里是代码的完整版本
#include <stdio.h>
#include <cs50.h>
long power();
int main(void)
{
//AMERX 15 STRT 34 OR 37
//MC 16 STRT 51, 52, 53, 54, 55
//VZA 13 OR 16 STRT 4
long input;
bool isValid = true;
string type;
int mod = 10;
int place = 1;
int num = 0;
int totalEven = 0;
int totalOdd = 0;
do
{
input = get_long("Number: ");
}
while(input < 0);
for(int i = 0; i < 16; i++)
{
num = ((input % mod) - (input % (mod /10))) / (mod/10);
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
else
{
totalOdd = totalOdd + num;
}
mod = mod * 10;
place++;
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
printf("%i , %i", totalEven, totalOdd);
}
if (isValid == true){
if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13))))
{
type = "AMEX\n";
}
else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
{
type = "MASTERCARD\n";
}
else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
{
type = "VISA\n";
}
else{
type = "error\n";
}
}
else
{
type = "INVALID\n";
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
printf("%s", type);
}
long power(int n, int p)
{
long result = 1;
for(int i = 0; i<p; i++)
{
result = result * n;
}
return result;
在查看您的代码时,我想指出一些错误。
- 您忘记了:
#include <string.h>
因为您在代码中声明了 string type
。
input = get_long("Number: ");
应该有自己的 do-while
循环,以防用户输入字母或不正确的数字。
if(place % 2 == 0){
totalEven = totalEven + num * 2;
}
else if (place % 2 != 0){
totalEven = totalEven + num;
}
第二部分应该 totalOdd = totalOdd + num
totalEven = totalEven + num * 2
同时对错。它仅在数字乘以 2 小于 10 时有效。如果 num * 2 >= 10,假设 num = 6,则 6 * 2 为 12,则为 1 + 2 + totalEven。
num = ((input % mod) - (input % (mod /10))) / (mod/10);
这个应该在第一个for loop
.
- 在
#include <math.h>
中,有一个名为 pow
的幂函数,它与您的 power()
函数完全相同。
我不是 Luhn 算法的专家,但当我阅读 https://en.wikipedia.org/wiki/Luhn_algorithm 时,我觉得你做错了。
引自https://en.wikipedia.org/wiki/Luhn_algorithm:
From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
我在您的代码中没有看到您处理粗体部分的任何地方。
而不是
totalEven = totalEven + num * 2;
我觉得你需要
int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;
就是说 - 我认为通过将输入存储为数字,您的实现比需要的复杂得多。您可以使用数字数组代替数字。
即 - 而不是
long input = 1122334455667788
使用
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit
这样算法就简单多了:
// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
digits[idx] = 2 * digits[idx];
if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}
// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
sum = sum + digits[idx];
}
如果您必须接收数字形式的输入,请首先调用一个将数字转换为数字数组的函数。您可以在 SO 上找到许多关于如何完成转换的示例。这里 Converting integer into array of digits 只是众多示例中的一个。
注意:我已经使用了 CS50X 库,因为这个问题似乎是同一个问题。
#include <stdio.h>
#include <cs50.h>
// Luhn's Algorithm
int main(void)
{
long cardNumber = get_long("Please, enter your card number: ");
int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
long temp = cardNumber;
while (temp > 0)
{
num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
while (num > 0)
{
remainder = num % 10;
sum1 += remainder; // Adding those products’ digits together
num /= 10;
}
temp /= 100;
}
// So as to restore the initial values of remainder and temp for the use in next loop
remainder = 0;
temp = cardNumber;
while (temp > 0)
{
remainder = temp % 10;
sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
temp /= 100;
}
((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
return 0;
}
我正在尝试用C语言实现Luhn的算法来检查信用卡的有效性,对于那些不知道的人......就是这样:
从数字开始,每隔一个数字乘以 2 倒数第二个数字,然后将这些产品的数字相加。
将未乘以 2 的数字的总和相加
如果总数的最后一位是 0(或者,更正式地说,如果总数
模 10 等于 0),该数字有效!
为了实现它,我遍历了整个数字,如果我所在的数字的模数 2 等于 0,那么我将乘以 2 并添加到一个名为 totalEven
的变量中。
如果不是这种情况,我会将我所在的数字添加到 totalOdd
而无需乘法。
然后我会将位置递增 1 并检查其他数字,直到达到 16(卡片的最大位数)。
稍后我会添加两个变量并检查总模十是否等于 0。如果这意味着信用卡号码正确,否则它是错误的。
代码如下:
#include <stdio.h>
#include <cs50.h>
//list of variables
//is the card valid
bool isValid = true;
// the creditcard number
long input;
//mod stands for modules, and is used to single out each number as seen later
int mod = 10;
//the location at which number I am checking
int place = 1;
//num is the number I am checking that has been singled out
int num = 0;
//total of numbers * 2 located at locations numbered with even numbers
int totalEven = 0;
//total of numbers located at locations numbered with odd numbers
int totalOdd = 0;
//gets input and stores it in well.. input
input = get_long("Number: ");
// 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.
num = ((input % mod) - (input % (mod /10))) / (mod/10);
//loops 16 times
for(int i = 0; i < 16; i++)
{
// if the place is even execute below
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
//else do this
else if (place % 2 != 0)
{
totalOdd = totalOdd + num;
}
//moves to the next number
mod = mod * 10;
place++;
}
//fufils the last step of the algorithm
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
问题是这个代码块给我无效或 !isValid
即使信用卡号应该是正确的并且我检查了我的“公式”并且它工作得很好...
我完全不知道该怎么做...我是一个谦虚的爱好者所以请不要因为上面的怪物而烤我。
这里是代码的完整版本
#include <stdio.h>
#include <cs50.h>
long power();
int main(void)
{
//AMERX 15 STRT 34 OR 37
//MC 16 STRT 51, 52, 53, 54, 55
//VZA 13 OR 16 STRT 4
long input;
bool isValid = true;
string type;
int mod = 10;
int place = 1;
int num = 0;
int totalEven = 0;
int totalOdd = 0;
do
{
input = get_long("Number: ");
}
while(input < 0);
for(int i = 0; i < 16; i++)
{
num = ((input % mod) - (input % (mod /10))) / (mod/10);
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
else
{
totalOdd = totalOdd + num;
}
mod = mod * 10;
place++;
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
printf("%i , %i", totalEven, totalOdd);
}
if (isValid == true){
if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13))))
{
type = "AMEX\n";
}
else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
{
type = "MASTERCARD\n";
}
else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
{
type = "VISA\n";
}
else{
type = "error\n";
}
}
else
{
type = "INVALID\n";
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
printf("%s", type);
}
long power(int n, int p)
{
long result = 1;
for(int i = 0; i<p; i++)
{
result = result * n;
}
return result;
在查看您的代码时,我想指出一些错误。
- 您忘记了:
#include <string.h>
因为您在代码中声明了string type
。 input = get_long("Number: ");
应该有自己的do-while
循环,以防用户输入字母或不正确的数字。if(place % 2 == 0){
totalEven = totalEven + num * 2;
}
else if (place % 2 != 0){
totalEven = totalEven + num;
}
第二部分应该totalOdd = totalOdd + num
totalEven = totalEven + num * 2
同时对错。它仅在数字乘以 2 小于 10 时有效。如果 num * 2 >= 10,假设 num = 6,则 6 * 2 为 12,则为 1 + 2 + totalEven。num = ((input % mod) - (input % (mod /10))) / (mod/10);
这个应该在第一个for loop
.- 在
#include <math.h>
中,有一个名为pow
的幂函数,它与您的power()
函数完全相同。
我不是 Luhn 算法的专家,但当我阅读 https://en.wikipedia.org/wiki/Luhn_algorithm 时,我觉得你做错了。
引自https://en.wikipedia.org/wiki/Luhn_algorithm:
From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
我在您的代码中没有看到您处理粗体部分的任何地方。
而不是
totalEven = totalEven + num * 2;
我觉得你需要
int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;
就是说 - 我认为通过将输入存储为数字,您的实现比需要的复杂得多。您可以使用数字数组代替数字。
即 - 而不是
long input = 1122334455667788
使用
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit
这样算法就简单多了:
// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
digits[idx] = 2 * digits[idx];
if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}
// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
sum = sum + digits[idx];
}
如果您必须接收数字形式的输入,请首先调用一个将数字转换为数字数组的函数。您可以在 SO 上找到许多关于如何完成转换的示例。这里 Converting integer into array of digits 只是众多示例中的一个。
注意:我已经使用了 CS50X 库,因为这个问题似乎是同一个问题。
#include <stdio.h>
#include <cs50.h>
// Luhn's Algorithm
int main(void)
{
long cardNumber = get_long("Please, enter your card number: ");
int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
long temp = cardNumber;
while (temp > 0)
{
num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
while (num > 0)
{
remainder = num % 10;
sum1 += remainder; // Adding those products’ digits together
num /= 10;
}
temp /= 100;
}
// So as to restore the initial values of remainder and temp for the use in next loop
remainder = 0;
temp = cardNumber;
while (temp > 0)
{
remainder = temp % 10;
sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
temp /= 100;
}
((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
return 0;
}