【问题标题】:Precision of double numbers with 17 or more digits具有 17 位或更多位的双精度数
【发布时间】:2014-07-17 00:58:40
【问题描述】:

在将大双精度(17 位以上)数字转换为整数时,我会出现精度损失。

#include <stdio.h>

int main() {
    int n = 20;
    double acum = 1;
    while (n--) acum *= 9;
    printf("%.0f\n", acum);
    printf("%llu\n", (unsigned long long)acum);
    return 0;
}

这段代码的输出是:

12157665459056929000
12157665459056928768

我不能使用 unsigned long long 进行计算,因为这只是一个伪代码,我需要真实代码的精度,其中包括除法。

如果我增加小数,第一个输出变为,例如 12157665459056929000.0000000000。 我已经尝试过 round(acum) 和 trunc(acum) 并且在这两种情况下结果都与第二个输出相同。他们不应该等于第一个吗??

我知道 float 只有 6 位小数精度,而 double 大约有 17 位。但是数字有什么问题?!?

【问题讨论】:

  • @Cornstalks 运行他的确切代码,您会发现该站点并没有给出他遇到的相同结果。编辑:为了后代,由于它已被删除,他链接到ideone.com
  • 我做过玉米秆,但我只得到零。 @Mike Precup 什么网站?
  • 他链接的网站。能给我们一些系统信息吗?如果该站点给出不同的结果,这可能取决于系统。
  • 我复制了这段代码并粘贴到compileonline.com/compile_cpp11_online.php,得到了预期的解决方案,即打印的两行都是一样的。
  • 最接近 12,157,665,459,056,928,801 的 IEEE 64 位二进制浮点数是 12157665459056928768

标签: c floating-point double precision digits


【解决方案1】:

实际上,当我将 acum 的类型更改为 unsigned long long 时:

unsigned long long acum = 1;

结果是:

12157665459056928801

当我使用 Python 计算准确答案时:

>>9**20 12157665459056928801L

你看到了吗?

12157665459056929000 根本不是一个准确的答案,实际上是准确的近似值。

然后我像这样更改代码:

printf("%llu\n", (unsigned long long)1.2157665459056929e+019);

printf("%llu\n", (unsigned long long)1.2157665459056928e+019);

printf("%llu\n", (unsigned long long)1.2157665459056927e+019);

printf("%llu\n", (unsigned long long)1.2157665459056926e+019);

结果是:

12157665459056928768

12157665459056928768

12157665459056926720

12157665459056926720

事实上 19 位已经超过了 cpp 的数字位数限制,转换这么大的数字的结果是出乎意料和不安全的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    相关资源
    最近更新 更多