为什么循环内的浮点数乘法不如循环外的精确?

lil*_*obo 1 c floating-point precision for-loop pow

我正在编写一个程序来计算sin(x)in ,使用泰勒级数x[0, 1]其中包括将其某些项提升到一定的幂。由于我是 C 新手,我决定编写自己的pow()函数只是为了练习。但后来我注意到我的程序无法正确计算正弦函数。经过检查,我发现在循环中将数字求幂不会产生与简单直接乘法相同的结果...v * v * v...

这是我的powr()功能和结果差异:

#include <stdio.h>    

double powr(double base, int power)
{
    if (power == 0) {
        base = 1;
    } else if (power > 0) {
        for (int i = 1; i < power; i++) {
            base *= base;
        }
    } else {
        // power is negative.
    }
    printf("In loop number to a power of 3: %lf\n", base);
    double hard_coded = 0.99 * 0.99 * 0.99;
    printf("Out of loop number to a power of 3: %lf\n", hard_coded); 

    return base;
}

int main(void)
{
    double num = 0.99;
    double num_to_power = powr(num, 3);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

In loop number to a power of 3: 0.960596
Out of loop number to a power of 3: 0.970299
Run Code Online (Sandbox Code Playgroud)

0.960596 和 0.970299 可能看起来并没有那么不同,但如果值更小,误差会变得更大。这是为什么?我该如何解决?

另外,我刚刚注意到,例如,如果我取像这样的小值0.123并将它们提高到 的幂。6我有一个类似的输出0.000000。我知道它太小而无法显示。但是如何打印一个后点数超过 6 个的浮点数呢?我也尝试过long double,也没成功。

Adr*_*ica 6

你的循环计算是错误的。该行将在每个循环中将“累积”值乘以在前一个循环中修改的base *= base;值,而不是乘以原始值(正如它应该的那样)。

您需要存储传递的base值并使用该保存的值作为每个循环的乘数:

double powr(double base, int power)
{
    double saved = base;
    if (power == 0) {
        base = 1;
    }
    else if (power > 0) {
        for (int i = 1; i < power; i++) {
            base *= saved;
        }
    }
    else {
        // power is negative.
    }

    printf("In loop number to a power of 3: %lf\n", base);
    double hard_coded = 0.99 * 0.99 * 0.99;
    printf("Out of loop number to a power of 3: %lf\n", hard_coded);

    return base;
}
Run Code Online (Sandbox Code Playgroud)

两个输出值将相等:

In loop number to a power of 3: 0.970299
Out of loop number to a power of 3: 0.970299
Run Code Online (Sandbox Code Playgroud)