3

我是编程新手,我试图让我的程序采用给定的数字,将其加倍,然后在用户输入的任何天数内继续加倍。我做了这个循环,它可以工作,但最终的数字是负数。我不确定如何阻止它出现负面影响,并希望能提供任何帮助。

int main(void)
{

    int d;
    int s;
    float a;

    do
    {
        printf ("Please enter the amount of days in the month: ");
        d = GetInt();   
    } while (d > 31 || d < 28);

    do 
    { 
        printf("Please enter the amount of pennies you start will start with: ");
        s = GetInt();
    } while( s < 0);

    do 
    {    
        s = s * 2;
        d = d - 1;
        a = s / 100.0;
        printf("%f\n", a);

    } while(d > 0);

    return 0;
}
4

3 回答 3

4

问题在这里:

s=s*2;

(尽管您应该确保始终初始化变量,例如s=0在循环之前。)

当数字大于存储类型时,整数没有特殊值,因此它们会溢出

这是一个可能发生的例子。想象一下,我们将整数存储为一系列 4 位,其中第一位表示数字为负数。如果我们然后开始在我们的系统中计数,我们会得到以下信息:

0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = -0
1001 = -1
1010 = -2

因此,您可以看到数字在计算机内部不断增长,但是当最高有效位被翻转时,它们转换为的内容突然变为负数。

计算机使用各种不同的方案来存储负数,但二进制码很常见。它比我在这里用来解释事物的系统更聪明,但要点保持不变:当数字变得太大时,它们就会变成负数。在int交叉点的情况下,通常是在您点击2^31或 2147483648 时。

一种解决方法是使用unsigned int,它大约使您可以表示的最大数字翻倍,或long, long long, unsigned long, 或unsigned long long。请记住,这不会解决您的问题,它只会为您提供更大的数字,您可以在问题出现之前使用。

limits.h您可以使用头文件找到最大的可用值;因为int它是INT_MAX

于 2013-03-05T22:00:30.737 回答
1
2^31 = 2147483648

如果超过 30 天,即使从 1 美分开始并将值加倍,您也会溢出一个整数。如果您从大量便士开始,您会更快溢出。

当整数溢出时,它显示为负值。根据下面的建议,它是未定义的行为。这是程序员使用的术语,新手不太了解。

于 2013-03-05T22:06:36.973 回答
1

C标准第6.5p5节:

如果在计算表达式期间出现异常情况(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义。

这说明任何int大于INT_MAX或小于的表达式INT_MIN都会导致问题。这些问题没有定义,所以你无法处理它们;最好避免这样的事情。在您的情况下,如上所述,计算包含负值。但是,这不是必需的。也许如果你要在不同的系统上用不同的编译器编译和运行它,你的程序可能会崩溃,或者它可能看起来像预期的那样工作,以某种方式在有限的存储空间中表示无限的值集,或者一只鸡可能无头跑了几分钟...谁知道呢?

您可以通过仔细选择具有更广泛范围的类型来避免此问题,正如其他答案中所涵盖的那样,并在您的输入上强制执行一个上限,这样就不会出现溢出。另一种方法是使用不应该溢出的任意精度算术库,例如GNU MP Bignum 。

于 2013-03-06T03:06:28.423 回答