c++ - double - 小数位

标签 c++ c precision ieee-754

根据我的阅读,数据类型 double 的值具有大约 15 位小数的精度。但是,当我使用十进制表示重复的数字(例如 1.0/7.0)时,我发现该变量包含 0.14285714285714285 的值——即 17 位(通过调试器)。

我想知道为什么它在内部表示为 17 位,为什么 15 的精度总是写在 ~15 处?

最佳答案

IEEE double 有 53 个有效位(即 DBL_MANT_DIG 中的 <cfloat> 的值)。这大约是 15.95 个十进制数字 (log10(253));实现集DBL_DIG到 15,而不是 16,因为它必须向下舍入。因此,您的精度几乎多了一个十进制数字(超出 DBL_DIG==15 所暗示的)。

nextafter()函数计算最接近给定数字的可表示数字;它可以用来显示给定数字的精确程度。

这个程序:

#include <cstdio>
#include <cfloat>
#include <cmath>

int main() {
    double x = 1.0/7.0;
    printf("FLT_RADIX = %d\n", FLT_RADIX);
    printf("DBL_DIG = %d\n", DBL_DIG);
    printf("DBL_MANT_DIG = %d\n", DBL_MANT_DIG);
    printf("%.17g\n%.17g\n%.17g\n", nextafter(x, 0.0), x, nextafter(x, 1.0));
}

在我的系统上给我这个输出:

FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.14285714285714282
0.14285714285714285
0.14285714285714288

(您可以将 %.17g 替换为 %.64g 以查看更多数字,但这些数字都不重要。)

如您所见,最后显示的十进制数字随每个连续值变化 3。 1.0/7.0 的最后一个显示数字的事实( 5 ) 恰好匹配数学值很大程度上是巧合;这是一个幸运的猜测。正确的四舍五入数字是6 ,而不是 5 .更换1.0/7.01.0/3.0给出这个输出:

FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.33333333333333326
0.33333333333333331
0.33333333333333337

如您所料,它显示了大约 16 位小数的精度。

关于c++ - double - 小数位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9999221/

相关文章:

c - 标准输入 C : Incorrect string if $ is present

c - 在谈论 C 语言时,动态创建的结构是什么意思?

c# - double 型属性(类)和 double 型字段(SQL 查询)中 float 表示的差异

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - CMake:如何传递预处理器宏

c - %p 是将变量的地址打印为指针,还是打印它指向的内容?

python - 机器 epsilon 的倍数是什么意思?

math - float 学坏了吗?

c++ - 类模板参数推导 - clang 和 gcc 不同

c++ - 运算符重载 : Ostream/Istream