【问题标题】:print 30 digits of a double value in c++在 C++ 中打印 30 位双精度值
【发布时间】:2017-06-24 18:53:16
【问题描述】:

我的理解是 numeric_limits::max_digits10 给出了小数点后可用的最大位数。但是,如果我将precision() 设置为大于此值的值,它仍然会给我超出此最大值的非零数字:

assert(std::numeric_limits<double>::max_digits10 == 17);
std::cout << std::setprecision(30) << double(.1) << '\n';

打印出来:

0.100000000000000005551115123126

超过 17 的数字是否不可信?

【问题讨论】:

  • Double 定义为 1.7E +/- 308(15 位),因此某些数字最多可以达到 308 位。但请先阅读@ThomasMatthews 的建议。
  • double 的精度不像 ±10^(-17) 那样固定,它取决于数字的值。较大的值具有较差的准确性,较小的数字 - 更好。换言之,值的±误差是相对于该值确定的。如您所见,数字 x 的误差约为 ±0.00000000000000005 * x
  • 一个关于浮点的信息太多的博客:exploringbinary.com/tag/floating-point
  • “非零数字”与有意义的数字不同。存储在变量中的浮点“数字”根本不是十进制数字:它们是二进制数字;并且不能保证将二进制转换为十进制的过程只会在用完有用的信息后才给你零。

标签: c++ floating-point precision


【解决方案1】:

将双精度的 53 位(隐含前导 1)尾数转换为二进制定点:

0.00011001100110011001100110011001100110011001100110011010

这等于十进制值

0.1000000000000000055511151231257827021181583404541015625

将问题的结果匹配到 30 位

0.100000000000000005551115123126

但是,第 54 位可能是什么是未知的,如果您将其视为可能值的范围,则正下方和上方的二进制定点数将是

0.000110011001100110011001100110011001100110011001100110001
0.000110011001100110011001100110011001100110011001100110101

表示十进制值:

0.099999999999999984734433411404097569175064563751220703125
0.100000000000000012490009027033011079765856266021728515625

这意味着 16 或 17 位精度。因此,仅当您将双精度数视为精确表示而不是最接近的表示时,30 位精度才是准确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    相关资源
    最近更新 更多