【发布时间】:2011-03-14 00:21:46
【问题描述】:
首先,这不是一个浮点新手问题。我知道浮点运算的结果(更不用说超越函数)通常无法准确表示,并且大多数终止小数不能准确表示为二进制浮点数。
也就是说,每个可能的浮点值都与一个有理数完全对应(有理数p/q,其中q 是2 的幂),而后者又具有精确的十进制表示。
我的问题是:如何有效地找到这个精确的十进制表示? sprintf 和类似的函数通常只指定最多几个有效数字来唯一确定原始浮点值;他们不一定打印确切的十进制表示。我知道我使用过一种算法,但它非常慢,O(e^2) 其中e 是指数。这是一个大纲:
- 将尾数转换为十进制整数。您可以通过将位分开以直接读取尾数来做到这一点,或者您可以编写一个凌乱的浮点循环,首先将值乘以 2 的幂,使其在 1
- 通过反复乘以或除以 2 来应用指数。这是对您生成的十进制数字 字符串 的操作。每〜3次乘法将在左侧增加一个额外的数字。每一个除法都会在右边增加一个数字。
这真的是最好的吗?我对此表示怀疑,但我不是浮点专家,我找不到一种方法来对数字的浮点表示进行以 10 为底的计算,而不会遇到不精确结果的可能性(乘以或除以除了 2 的幂之外的任何东西都是浮点数的有损运算,除非你知道你有空闲位可以使用)。
【问题讨论】:
-
最后,我只是用 base-1e9 替换了旧的 base-10 代码,并在随后的大多数迭代中重复乘法/除以 2 与 mult 乘 2^29 和 div 乘以 2^9尾部乘以 mult/div 乘以 2。生成的代码在相当短的时间内打印出最小的 80 位
long double,所以我很高兴。 -
Jon Skeet 有一个DoubleConverter class,可以打印精确的十进制表示。它是用 C# 编写的,但您可以将其转换为 C stackoverflow.com/questions/4732680/…
标签: c algorithm math floating-point