0

这是一个C代码;

#include<stdio.h>
#include<math.h>
int main()
{
    double n=10.0;
    double automatic = pow(10.0,log10(n)-log10(5.0));
    printf("%.9lf\n",log10(n)-log10(5.0));
    printf("%.9lf\n",pow(10.0,0.30102996));
    double manual = pow(10.0,0.30102996);
    printf("%.9lf %lf\n",automatic, floor(automatic));
    printf("%.9lf %lf\n",manual,floor(manual));
    return 0;
}

输出是:

0.301029996
1.999999836
2.000000000 1.000000
1.999999836 1.000000

从输出中我可以推断出在 pow(x,y) 中 y 被四舍五入为 6 位,因为它的签名是 pow(double x, double y) 所以 0.301029996 变为 0.301030 这就是为什么自动的值是 2.000000000 否则它将是和手册一样。

我的问题:

  1. 我的推断正确吗?
  2. 如果第一个问题的答案是正确的,那么我们如何绕过这个四舍五入来获得更准确的结果?
4

1 回答 1

3

pow不四舍五入到 6 位数。它使用双精度,对于 IEEE 双精度是 52 位有效数字(大约 15 位小数)。在该精度下,它可能精确到最后一位数字,也可能不精确,但通常很接近。

以 10 为底的对数 2 的精确值接近0.301029995663981195213738894724(来源:Wolfram Alpha)。它是一个无理数,因此不能用任何数字系统(十进制或二进制)精确表示。

您的结果表明,log10(n)-log10(5.0)返回的值比精确的以 10 为底的对数 2 更接近0.30102996。您得到的原因1.999999836是,当您将其替换为0.30102996. 顺便说一句,这不是四舍五入的值 - 数一下 9。

您的调用pow(10.0,log10(n)-log10(5.0))返回的结果略小于2(如 所示floor),但足够接近,可以在 9 个位置四舍五入为 2。使用 double 类型不会比这更好。

所以我真的不知道你所说的“避免四舍五入”是什么意思。如果您不想使值不那么准确,请不要手动将其四舍五入到 9 位,并且在复制时当然不要遗漏任何数字;-)

于 2012-08-12T15:11:06.037 回答