这是我的第一个C作业,所以我的错误对你来说可能是非常明显的,如果是这样,我会提前道歉。然而,这对我来说似乎很不寻常(不只是工作,而是有一些奇怪的输出),所以我想我应该四处询问。我正在尝试计算交替谐波系列的总和。这是应该这样做的函数(它返回一个double)。
double series(void){
double sum = 0.0;
int i,x;
for (i = 1; i > 0 ; i = i+1)
{
if (sum - (sum - 1.0/x) == 0 || sum - (sum + 1.0/x) == 0)
{
printf("To infinity and beyond... almost!\n");
return sum;
}
else if (i % 2 != 0)
{
sum = sum - 1.0/x;
}
else if (i % 2 == 0)
{
sum = sum + 1.0/x;
}
else
{
printf("How did I end up here?\n");
}
}
printf("I ESCAPED THE LOOP\n");
return 1.0*i;
}
当我运行程序时,它总是在最后几行结束(打印行I ESCAPED THE LOOP,因此for循环结束,而它应该运行直到第一个if条件满足。最后一行是不应该达成)。对于i,输出 - 函数的返回值 - 为-21473822648.000000。一个负数(实际上main中的输出是正数,但是它在那里乘以负1并且除去-1.0只会将符号更改为它不应该的那个),当唯一改变我的东西时应该在for循环介绍中,我是i = 1和++ i。这是怎么发生的? main主要做的只是调用函数,将double的值设置为函数返回值的负数并打印该值。
我刚刚意识到if()语句中的操作顺序可能是错误的,但是我用所有内容的额外括号修复了它。它没有效果。
哦,这实际上不是整个问题,我实际上应该找出哪些是最好和最差的求和顺序。我只是想看看我是否能编写一个能够实现它的程序。任何与浮点运算相关的材料的链接都将受到赞赏。
提前感谢所有人和任何人的建议。
答案 0 :(得分:1)
使用更正的功能(per comments)
double series(void){
double sum = 0.0, x;
int i;
for (i = 1; i > 0 ; i = i+1)
{
x = 1.0*i;
if (sum - (sum - 1.0/x) == 0 || sum - (sum + 1.0/x) == 0)
{
printf("To infinity and beyond... almost!\n");
return sum;
}
else if (i % 2 != 0)
{
sum = sum - 1.0/x;
}
else if (i % 2 == 0)
{
sum = sum + 1.0/x;
}
else
{
printf("How did I end up here?\n");
}
}
printf("I ESCAPED THE LOOP\n");
return 1.0*i;
}
要消除使用未初始化变量的未定义行为,让我们看看会发生什么。
sum
的值始终在-1.0
和0.0
之间,接近(模数浮点舍入)-log 2
(自然对数)。
i
是int
。从你得到的结果来看,我们可以推断出({严格来说逻辑上,但超出合理怀疑)int
在您的平台上有32位,因此i < 2^31 = 2147483648
。因此,要添加或减去的术语1.0/i
的幅度大于2^(-31)
。由于double
s通常具有53位精度,因此每次加法/减法都会更改sum
sum - (sum - 1.0/x) == 0 || sum - (sum + 1.0/x) == 0
永远不会成真。因此循环不会以该条件结束,并且i
会递增,直到达到INT_MAX
,然后再次递增。
最后一个增量溢出。有符号整数的溢出会调用未定义的行为,但在这种情况下,发生了环绕的常见行为,i
则包含值INT_MIN = -2147483648
。然后循环条件i > 0
的计算结果为false,循环结束时没有return
函数。