0

这是我的第一个 C 作业,所以我的错误对你来说可能很明显,如果是这种情况,我提前道歉。然而,这对我来说似乎很不寻常(不仅仅是工作,而且有一些奇怪的输出),所以我想我应该四处问问。我正在尝试计算交替谐波系列的总和。这是应该做的函数(它返回一个双精度)。

    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;

}

当我运行程序时,它总是在最后几行结束(打印我 ESCAPED THE LOOP 的行,所以 for 循环结束,而它应该运行直到满足第一个 if 条件。最后一行并不意味着达到)。并且输出——函数的返回值——对于 i 是 -21473822648.000000。一个负数(实际上 main 中的输出是正数,但它在那里乘以负一,并且删除 -1.0 只不过将符号更改为不应该的符号),当唯一改变的事情我应该在 for 循环介绍中为 i=1 和 ++i 。这是怎么发生的?main 唯一要做的就是调用函数,将双精度值设置为函数返回值的负数并打印该值。

而且我刚刚意识到 if() 语句中的操作顺序可能是错误的,但是我在所有内容周围都加上了额外的括号来修复它。它没有效果。

哦,这实际上不是全部问题,我实际上应该找出哪些是最好和最差的求和顺序。我只是想看看我是否可以编写一个程序来做到这一点。任何指向浮点算术相关材料等的链接将不胜感激。

在此先感谢所有人以及任何人可能有的任何建议。

4

1 回答 1

1

使用更正的功能(根据评论

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你的平台上 s 有 32 位,因此i < 2^31 = 2147483648. 因此,要添加或减去的项1.0/i的量级大于2^(-31)。由于doubles 通常具有 53 位精度,因此每个加法/减法的变化sum足以使

sum - (sum - 1.0/x) == 0 || sum - (sum + 1.0/x) == 0

永远不会成为真的。因此循环不会以该条件结束,i而是递增直到达到INT_MAX,然后再增加一次。

最后一个增量溢出。有符号整数的溢出会调用未定义的行为,但在这种情况下,会发生回绕的常见行为,i然后包含 value INT_MIN = -2147483648。然后循环条件i > 0评估为假,循环结束而不return从函数中获取。

于 2012-11-03T19:48:48.203 回答