Printf结果是否定的

时间:2013-03-05 21:17:12

标签: c negative-number

我是编程的新手,我试图让我的程序获取给定的数字,加倍,然后在用户输入的许多天内继续加倍。我做了这个循环并且它可以工作,但最终的数字是负面的。我不确定如何阻止它出现否定,并希望得到任何帮助。

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;
}

3 个答案:

答案 0 :(得分:4)

问题在于:

s=s*2;

(虽然你应该确保始终初始化你的变量,例如循环前的s=0。)

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

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

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

所以你可以看到数字在计算机内部不断增长,但是当最重要的部分被打开时,它们转化为突然变为负数。

计算机使用各种不同的方案来存储负数,但Two's Complement很常见。它比我用来解释这里的东西的系统更聪明,但基本点仍然是相同的:当数字变得太大时,它们就会变成负数。在int的情况下,交叉点通常是在您点击2^31或2147483648时。

解决方法是使用unsigned int,大致可以代表您可以代表的最大数字的两倍,或longlong longunsigned longunsigned long long。请记住,这不会解决您的问题,只会在出现问题之前为您提供更大的数字。

您可以使用limits.h头文件找到最大可用值;对于intINT_MAX

答案 1 :(得分:1)

2^31 = 2147483648

如果超过30天,您将溢出一个整数,即使从1便士开始并将该值加倍。如果你从更多的便士开始,你会很快溢出。

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

答案 2 :(得分:1)

C标准第6.5p5节:

  

如果在评估过程中出现异常情况   表达式(即,如果结果未在数学上定义或   不在其类型的可表示值的范围内),行为   未定义。

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

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