【问题标题】:Problem in a code for CS50 CREDIT assignmentCS50 CREDIT 分配代码中的问题
【发布时间】:2020-05-27 11:46:29
【问题描述】:

我正在尝试为 CS50(信用)中设置的信用问题编写代码,我才刚开始,但我遇到了一个问题。现在我正在尝试提取卡位以便稍后使用它们并检查提取是否顺利。代码似乎对卡号中的每个数字都有效,除了第 12 位(从末尾开始)。

例如 卡号: 输入:1111111111111111 输出:1111111111101111

虽然在某些情况下不会出现此问题:

输入: 1234567890123456 输出: 1234567890123456

这是我的代码(请不要太苛刻,我是新手:)) 我知道还有其他方法可以获得这些数字,但我现在真的很想知道为什么它不起作用。提前致谢!

#include <stdio.h>
#include <cs50.h>

long card_no(void);
int main(void)
{
    long card = card_no();
    int one = (card % 10);
    int two = (card % 100 - card % 10) * 0.1;
    int tree = (card % 1000 - card % 100) * 0.01;
    int four = (card % 10000 - card % 1000) * 0.001;
    int five = (card % 100000 - card % 10000) * 0.0001;
    int six = (card % 1000000 - card % 100000) * 0.00001;
    int seven = (card % 10000000 - card % 1000000) * 0.000001;
    int eight = (card % 100000000 - card % 10000000) * 0.0000001;
    int nine = (card % 1000000000 - card % 100000000) * 0.00000001;
    int ten = (card % 10000000000 - card % 1000000000) * 0.000000001;
    int eleven = (card % 100000000000 - card % 10000000000) * 0.0000000001;
    int twelve = (card % 1000000000000 - card % 100000000000) * 0.00000000001;
    int thirteen = (card % 10000000000000 - card % 1000000000000) * 0.000000000001;
    int forteen = (card % 100000000000000 - card % 10000000000000) * 0.0000000000001;
    int fifteen = (card % 1000000000000000 - card % 100000000000000) * 0.00000000000001;
    int sixteen = (card % 10000000000000000 - card % 1000000000000000) * 0.000000000000001;

    printf("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i\n", sixteen, fifteen, forteen, thirteen, twelve, eleven, ten, nine, eight, seven, six, five, four, tree, two, one);

}

//Prompt user for 13 to 16 digits card number
long card_no(void)
{
    long n;
    do
    {
       n = get_long("Card number:\n"); 
    }
    while (n < 1000000000000 || n > 9999999999999999);
    return n;
}

【问题讨论】:

  • 卡号可能放不下。为什么不作为字符串处理,分别获取每个数字?
  • 或者当您与浮点数相乘时可能会出现不精确。为什么不使用整数除法,/
  • 程序到底应该做什么?无论如何,它看起来很奇怪。

标签: c cs50


【解决方案1】:

浮点数学并不精确 - 像 0.1 这样的值不能完全 用有限的位数表示,所以你只能得到像 0.099...0.1000...1 这样的近似值像那样。因此,在计算完您的第五位数字后,您会得到 0.9... 的值,当转换为 int 时会得到 0

另一个不依赖于浮点数学的选项是通过增加幅度来除数并获取结果的% 10。爱荷华,

(123 /   1) % 10  == 123 % 10 == 3
(123 /  10) % 10  ==  12 % 10 == 2
(123 / 100) % 10  ==   1 % 10 == 1

整数除法产生整数结果 - 任何小数部分都将被丢弃。

方便的提示,当你发现自己创建了一堆具有序号名称(firstsecondthirdonetwothree)的相同类型的变量时,这真的是强烈提示您要使用 数组

#define  NUM_DIGITS 16
int digits[NUM_DIGITS];

/** 
 * get card number as before
 */

long magnitude = 1;
/**
 * Arrays are indexed from 0 to N-1
 */
for ( size_t i = 0; i < NUM_DIGITS; i++ ) 
  digits[i] = (card / magnitude) % 10;
  magnitude *= 10;
}

/**
 * I typically use size_t for array indices, which is an unsigned type.
 * This means it cannot represent negative values.  If we loop while "i >= 0",
 * then the loop will never exit, since subtracting 1 from 0 will "wrap
 * around" to the largest value.  So even though the array is indexed from
 * NUM_DIGITS-1 to 0, we loop over NUM_DIGITS to 1 and subtract 1 from 
 * i in the subscript operation.
 */
for ( size_t i = NUM_DIGITS; i > 0; i-- ) 
  printf( "%d", digits[i-1] );

【讨论】:

    【解决方案2】:

    这段代码可能会向您展示一种更简单的方法。
    它一次提取一个数字的所有数字,而不使用像 10000000 这样越来越大的数字。

    #include <stdio.h>
    
    int main(void) {
        unsigned long card_number = 564879165464;
        int counter = 1;
    
        while(card_number)
        {
            printf("Digit %d = %d\n", counter++, card_number % 10);
            card_number /= 10;
        }
    
        return 0;
    }
    

    输出

    Digit 1 = 4
    Digit 2 = 6
    Digit 3 = 4
    Digit 4 = 5
    Digit 5 = 6
    Digit 6 = 1
    Digit 7 = 9
    Digit 8 = 7
    Digit 9 = 8
    Digit 10 = 4
    Digit 11 = 6
    Digit 12 = 5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      • 2021-12-20
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多