C 从数字中获取特定数字时的值不正确

C 从数字中获取特定数字时的值不正确,c,math,cs50,C,Math,Cs50,我的输出似乎与我(经过测试的)计算不符 const char* credit_card(void) { long card = get_card(); PRINT_VAL(card); //prints value to console if(checksum(card)) { int cardlen = log10(card)+1; //gets length of card int left = card % (long) pow(

我的输出似乎与我(经过测试的)计算不符

const char* credit_card(void) {
    long card = get_card();
    PRINT_VAL(card); //prints value to console

    if(checksum(card)) {

        int cardlen = log10(card)+1; //gets length of card
        int left = card % (long) pow(10, log10(card)); //should give first digit
        PRINT_VAL(left);

        int left_two = card % (long) pow(10, (log10(card)-1)); //should give 1st 2 digits
        PRINT_VAL(left_two);

        switch(cardlen) {
            case 13:
            if(left == 4) {return "VISA";}
            return "INVALID visa13";

            case 16:
            if(left == 4) {return "VISA";}

            if(left_two >= 51 && left_two <= 55) {return "MASTERCARD";}
            return "INVALID visa/mst16";

            case 15:
            if(left_two == 34 || left_two == 37) {return "AMEX";}
        }
    }
    return "INVALID - CHECKSUM FAILED";
}
测试2
正如您所看到的,它没有为
left
left\u two
返回正确的数字。对于
案例13
案例15
我也没有得到正确的结果。然而,
left
left\u两个
的计算在我的计算器上给出了正确的结果。这里哪里出错了?

首选的实现是使用卡号的字符串表示来检查数字,如注释中所述。这将避免与潜在的整数溢出、浮点精度有限和前导零相关的问题

以下内容解决了OP发布代码的问题

上面计算卡号的位数(假设64位整数,不计算前导零)

然而,这是:

  • 不使用先前计算的
    cardlen
    位数,因此它被错误的数字除掉(第一个数字基本上是被
    card
    除掉,但精度有所降低)

  • 使用
    %
    模数而不是
    /
    整数除法,因此它是尾随数字而不是前导数字

更正版本应为:

 int left = card / (long) pow(10, cardlen - 1);      //should give first digit
 int left_two = card / (long) pow(10, cardlen - 2);  //should give 1st 2 digits

处理整数时不要使用浮点运算您确定这些计算吗?忽略舍入错误,
pow(10,log10(x))
将计算为
x
,并且您尝试查找左侧数字的结果将始终为零。
long card
-通常为32位。要存储16位整数,需要64位。对数?权力?这只是一串数字。对于卡片、电话、PIN、房屋等号码,请使用字符串。如何从整数中恢复前导零?当然:这大大简化了代码,在我看来,您走错了路。此外,请使用
'4'
而不是ASCII值
52
,等等。一个“数字”并不总是意味着一个整数,“字符”并不总是意味着
char
——可以理解,这很容易做出假设。使用
log10(卡片)
在接近10次方的边缘情况下会出现问题,如果
card@chux完全正确,则会出现严重故障。人们永远不应该使用浮点来解决需要精确解的整数问题(除了一些非常特殊的情况,需要特别小心)。这是顶部免责声明的部分内容。然而,除此之外,OP的代码还有几个纯粹的数学问题,其余的答案都解决了这些问题。但该方法的其他问题仍然如前所述。
Enter your card number:
4111111111111111
**val of card: 4111111111111111**
**val of left: 3**
**val of left_two: 11**
Card Type: INVALID foo visa/mst16
int cardlen = log10(card)+1; //gets length of card
int left = card % (long) pow(10, log10(card));         //should give first digit
int left_two = card % (long) pow(10, (log10(card)-1)); //should give 1st 2 digits
 int left = card / (long) pow(10, cardlen - 1);      //should give first digit
 int left_two = card / (long) pow(10, cardlen - 2);  //should give 1st 2 digits