【问题标题】:How does computer convert floating point numbers to decimal string?计算机如何将浮点数转换为十进制字符串?
【发布时间】:2016-11-21 00:13:58
【问题描述】:

当我运行以下代码时,输​​出准确为十进制数字 2500

(ubuntu 上的 g++ 5.3.1)

#include<iostream>
#include<cmath>

using namespace std;

int main(){
    cout.precision(0);
    cout << fixed << pow(2.0,500.0);
    return 0;
}

我想知道 C++ 是如何以如此高的精度将此浮点数转换为十进制字符串的。

我知道 2500 可以准确地以 IEEE 754 格式表示。但我认为mod 10divided by 10 会导致浮点数的精度损失。转换进行时使用什么算法?

【问题讨论】:

标签: c++ math floating-point precision


【解决方案1】:

是的,2500 存在精确的双精度浮点表示。但是,您不应该假设 pow(2.0,500.0) 会产生这个值。无法保证函数 pow 的准确性,您可能会发现源自 pow(10.0, 2.0)SO questions 不会产生 100.0,尽管数学结果也可以完美表示。

但无论如何,要回答您的问题,从浮点二进制表示到十进制的转换通常不依赖于浮点运算,这对于最终结果的预期准确性来说确实太不准确了。一般来说,准确的转换需要reliance on big integer arithmetics。例如,在 2500 的情况下,朴素的算法是将二进制 1000…&lt;500 zeroes in total&gt;… 写入的大整数重复除以 10。

在某些情况下可以使用浮点运算,例如利用 10 到 1023 的幂在 IEEE 754 双精度中精确表示的事实。但是二进制浮点和十进制浮点之间的正确舍入转换通常总是需要大整数运算,这在远离 1.0 时尤其明显。

【讨论】:

  • 或 BigDecimal(内部经常使用 BigInteger)。
  • 我假设 pow() 在内部使用基于 e 和自然对数的幂运算,因此这是准确的,确实可能纯属巧合。或者可能某些 pow() 实现对于整数参数是不同的?
  • @RudyVelthuis 不管它是如何实现的,它只需要被设计成“忠实”(错误 pow(2.0,500.0) 会以 0x1.0p500 出现,因为这是距离 1 ULP 2^500 的唯一双精度数。
  • 我猜有很多编译器运行时这不适用,即你会看到超过 1 ulp 的差异。
  • @RudyVelthuis 是的,这是stackoverflow.com/questions/18417788/… 的惨痛教训
猜你喜欢
  • 2020-10-17
  • 2013-07-16
  • 2020-12-11
  • 2014-06-18
  • 2014-03-01
  • 2017-09-28
  • 2010-11-07
  • 2012-08-22
相关资源
最近更新 更多