我是编程的新手,我试图让我的程序获取给定的数字,加倍,然后在用户输入的许多天内继续加倍。我做了这个循环并且它可以工作,但最终的数字是负面的。我不确定如何阻止它出现否定,并希望得到任何帮助。
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;
}
答案 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
,大致可以代表您可以代表的最大数字的两倍,或long
,long long
,unsigned long
或unsigned long long
。请记住,这不会解决您的问题,只会在出现问题之前为您提供更大的数字。
您可以使用limits.h
头文件找到最大可用值;对于int
,INT_MAX
。
答案 1 :(得分:1)
2^31 = 2147483648
如果超过30天,您将溢出一个整数,即使从1便士开始并将该值加倍。如果你从更多的便士开始,你会很快溢出。
当整数溢出时,它显示为负值。根据以下建议,它是未定义的行为。这是程序员使用的术语,而新人们并不了解。
答案 2 :(得分:1)
C标准第6.5p5节:
如果在评估过程中出现异常情况 表达式(即,如果结果未在数学上定义或 不在其类型的可表示值的范围内),行为 未定义。
这说明任何大于int
或小于INT_MAX
的{{1}}表达式都会导致问题。这些问题没有定义,所以你无法处理;最好避免这样的事情。在您的情况下,计算包含负值,如上所述。但是,这不是必需的。也许如果您要在不同的系统上编译和运行它,使用不同的编译器,您的程序可能会崩溃,或者它似乎按预期工作,以某种方式在有限的存储空间中表示无限的值集,或者鸡可能无头无息地跑了几分钟......谁知道?
您可以通过仔细选择范围更广的类型来避免此问题,如其他答案中所述,并在输入上强制执行上限值,以便不会出现溢出。另一种方法是使用任意精度算术库,例如GNU MP Bignum,它不应该溢出。