循环早结束,为循环计数器产生负值(当i = 1; ++ i时)

时间:2012-11-03 18:42:06

标签: c loops for-loop series floating

这是我的第一个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()语句中的操作顺序可能是错误的,但是我用所有内容的额外括号修复了它。它没有效果。

哦,这实际上不是整个问题,我实际上应该找出哪些是最好和最差的求和顺序。我只是想看看我是否能编写一个能够实现它的程序。任何与浮点运算相关的材料的链接都将受到赞赏。

提前感谢所有人和任何人的建议。

1 个答案:

答案 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.00.0之间,接近(模数浮点舍入)-log 2(自然对数)。

iint。从你得到的结果来看,我们可以推断出({严格来说逻辑上,但超出合理怀疑)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函数。