CS50 Luhn 的 C 算法
CS50 Luhn's Algorithm in C
我是 C 的新手,正在学习 CS50。我无法让我的代码工作。我几乎肯定 for 语句是正确的。 for语句给出的和是正确的。
我认为这与 if 语句中的 (floor(ccNumber / pow(10,13) == 34)
有关。
卢恩算法的解释:https://cs50.harvard.edu/x/2020/psets/1/credit/
用于测试的示例信用卡号码:https://www.freeformatter.com/credit-card-number-generator-validator.html
#include <stdio.h>
#include <cs50.h>
#include <math.h>
void credit(long ccNumber);
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
while (ccNumber < 0);
{
int sum = 0;
long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && (floor(ccNumber / pow(10,13) == 34) || (floor(ccNumber / pow(10,13) == 37))))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) && (floor(ccNumber / pow(10,12) == 4) || floor(ccNumber / pow(10,15) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14) >= 51) || (floor(ccNumber / pow(10,14) <= 55)))))
{
printf("%s\n", "MASTERCARD");
}
}
}
我或多或少在维基百科上关注的伪代码::
function checkLuhn(string purportedCC) {
int sum := integer(purportedCC[length(purportedCC)-1])
int nDigits := length(purportedCC)
int parity := nDigits modulus 2
for i from 0 to nDigits - 2 {
int digit := integer(purportedCC[i])
if i modulus 2 = parity
digit := digit × 2
if digit > 9
digit := digit - 9
sum := sum + digit
}
return (sum modulus 10) = 0
}
信用卡号很大,你确定long
就够了,不需要long long
除此之外,在您的表达式中,例如 floor(ccNumber / pow(10,13) == 34)
,')' 位置错误,您想要 floor(ccNumber / pow(10,13)) == 34
,当然其他人也一样:
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37)))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55)))
{
printf("%s\n", "MASTERCARD");
}
但在
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
你冒着得到不好结果的风险,你需要检查 (floor(ccNumber / pow(10,12)) == 4)
仅当 nDigits == 13
和 (floor(ccNumber / pow(10,15)) == 4)
仅当 nDigits == 16
并且你可以简化为:
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4))
最后 :
#include <stdio.h>
#include <math.h>
void credit(long long ccNumber);
int main(void)
{
long long cc[] = { 4532057997187363ll, // visa
4485661945778178ll, // visa
2720995573736457ll, // MasterCard
2720998284576493ll, // MasterCard
375137447049450ll, // amex
378572901284556ll, // amex
};
for (int i = 0; i != sizeof(cc)/sizeof(*cc); ++i)
credit(cc[i]);
return 0;
}
void credit(long long ccNumber)
{
int sum = 0;
long long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
//printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37))) {
printf("%lld %s\n", ccNumber, "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4)) {
printf("%lld %s\n", ccNumber, "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55))) {
printf("%lld %s\n", ccNumber, "MASTERCARD");
}
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall f.c -lm
pi@raspberrypi:/tmp $ ./a.out
4532057997187363 VISA
4485661945778178 VISA
2720995573736457 MASTERCARD
2720998284576493 MASTERCARD
375137447049450 AMEX
378572901284556 AMEX
pi@raspberrypi:/tmp $
还请注意,进行浮点计算是有风险的,您可以只使用 long long
关于:
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
对 credit()
的调用正在传递变量的内容:ccnumber
而不是指向 ccnumber
的指针。所以被调用的函数:credit()
永远不能改变 main()
.
中的那个值
建议:
int main(void)
{
long ccNumber = 0;
credit( &ccNumber );
}
void credit(long * ccNumber)
{
do
{
*ccNumber = get_long("Enter a credit card number: ");
}
一般来说,永远不要比较浮点值和整数值是否相等,所以下面这种表达式是非常不可靠的:
(floor(ccNumber / pow(10,13) == 34)
此外,这样的表达式实际上只是将 ccnumber
的两个数字与 34 进行比较。最好将信用卡号作为字符串读取,然后将这两个数字与 ccnumber[ first digit position ] == 3 && ccnumber[ second digit position ] == 4
进行比较。所有其他使用 pow()
的表达式都存在类似的考虑
因此,建议通过以下方式获取信用卡号:
string ccnumber = get_string( "enter credit card number" );
结果将是指向包含信用卡号的字符串的指针。每个 'interesting' 数字都可以作为索引(从 0 开始)进入信用卡号码
但是,如果您真的不想使用 char 数组,您可以替换像这样的表达式;
(floor(ccNumber / pow(10,13) == 34)
与:
(ccNumber / 10000000000000 == 34)
#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 的新手,正在学习 CS50。我无法让我的代码工作。我几乎肯定 for 语句是正确的。 for语句给出的和是正确的。
我认为这与 if 语句中的 (floor(ccNumber / pow(10,13) == 34)
有关。
卢恩算法的解释:https://cs50.harvard.edu/x/2020/psets/1/credit/
用于测试的示例信用卡号码:https://www.freeformatter.com/credit-card-number-generator-validator.html
#include <stdio.h>
#include <cs50.h>
#include <math.h>
void credit(long ccNumber);
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
while (ccNumber < 0);
{
int sum = 0;
long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && (floor(ccNumber / pow(10,13) == 34) || (floor(ccNumber / pow(10,13) == 37))))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) && (floor(ccNumber / pow(10,12) == 4) || floor(ccNumber / pow(10,15) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14) >= 51) || (floor(ccNumber / pow(10,14) <= 55)))))
{
printf("%s\n", "MASTERCARD");
}
}
}
我或多或少在维基百科上关注的伪代码::
function checkLuhn(string purportedCC) {
int sum := integer(purportedCC[length(purportedCC)-1])
int nDigits := length(purportedCC)
int parity := nDigits modulus 2
for i from 0 to nDigits - 2 {
int digit := integer(purportedCC[i])
if i modulus 2 = parity
digit := digit × 2
if digit > 9
digit := digit - 9
sum := sum + digit
}
return (sum modulus 10) = 0
}
信用卡号很大,你确定long
就够了,不需要long long
除此之外,在您的表达式中,例如 floor(ccNumber / pow(10,13) == 34)
,')' 位置错误,您想要 floor(ccNumber / pow(10,13)) == 34
,当然其他人也一样:
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37)))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55)))
{
printf("%s\n", "MASTERCARD");
}
但在
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
你冒着得到不好结果的风险,你需要检查 (floor(ccNumber / pow(10,12)) == 4)
仅当 nDigits == 13
和 (floor(ccNumber / pow(10,15)) == 4)
仅当 nDigits == 16
并且你可以简化为:
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4))
最后 :
#include <stdio.h>
#include <math.h>
void credit(long long ccNumber);
int main(void)
{
long long cc[] = { 4532057997187363ll, // visa
4485661945778178ll, // visa
2720995573736457ll, // MasterCard
2720998284576493ll, // MasterCard
375137447049450ll, // amex
378572901284556ll, // amex
};
for (int i = 0; i != sizeof(cc)/sizeof(*cc); ++i)
credit(cc[i]);
return 0;
}
void credit(long long ccNumber)
{
int sum = 0;
long long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
//printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37))) {
printf("%lld %s\n", ccNumber, "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4)) {
printf("%lld %s\n", ccNumber, "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55))) {
printf("%lld %s\n", ccNumber, "MASTERCARD");
}
}
编译与执行:
pi@raspberrypi:/tmp $ gcc -Wall f.c -lm
pi@raspberrypi:/tmp $ ./a.out
4532057997187363 VISA
4485661945778178 VISA
2720995573736457 MASTERCARD
2720998284576493 MASTERCARD
375137447049450 AMEX
378572901284556 AMEX
pi@raspberrypi:/tmp $
还请注意,进行浮点计算是有风险的,您可以只使用 long long
关于:
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
对 credit()
的调用正在传递变量的内容:ccnumber
而不是指向 ccnumber
的指针。所以被调用的函数:credit()
永远不能改变 main()
.
建议:
int main(void)
{
long ccNumber = 0;
credit( &ccNumber );
}
void credit(long * ccNumber)
{
do
{
*ccNumber = get_long("Enter a credit card number: ");
}
一般来说,永远不要比较浮点值和整数值是否相等,所以下面这种表达式是非常不可靠的:
(floor(ccNumber / pow(10,13) == 34)
此外,这样的表达式实际上只是将 ccnumber
的两个数字与 34 进行比较。最好将信用卡号作为字符串读取,然后将这两个数字与 ccnumber[ first digit position ] == 3 && ccnumber[ second digit position ] == 4
进行比较。所有其他使用 pow()
因此,建议通过以下方式获取信用卡号:
string ccnumber = get_string( "enter credit card number" );
结果将是指向包含信用卡号的字符串的指针。每个 'interesting' 数字都可以作为索引(从 0 开始)进入信用卡号码
但是,如果您真的不想使用 char 数组,您可以替换像这样的表达式;
(floor(ccNumber / pow(10,13) == 34)
与:
(ccNumber / 10000000000000 == 34)
#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;
}