使用2"浮动"模拟"双"

58 c c++ algorithm floating-point precision

我正在编写一个只支持32位单精度浮点运算的嵌入式硬件程序.但是,我实现的算法需要64位双精度加法和比较.我试图double使用两个元组的模块来模拟数据类型float.因此,a double d将被模拟为struct包含元组:(float d.hi, float d.low).

使用字典顺序进行比较应该是直截了当的.然而,添加有点棘手,因为我不确定应该使用哪个基数.应该是FLT_MAX吗?我怎样才能检测到携带?

如何才能做到这一点?


编辑(清晰度):我需要额外的有效数字而不是额外的范围.

nju*_*ffa 81

double-float是一种技术,它使用单精度数对,几乎达到单精度算术精度的两倍,同时略微降低单精度指数范围(由于中间下溢和范围远端溢出) .基本算法由TJ Dekker和William Kahan在20世纪70年代开发.下面我列出了两篇最近的论文,展示了这些技术如何适应GPU,但是这些论文中涵盖的大部分内容都适用于独立于平台,因此应该对手头的任务有用.

http://hal.archives-ouvertes.fr/docs/00/06/33/56/PDF/float-float.pdf GuillaumeDaGraça,David Defour在图形硬件上实现浮动浮动运算符,第7次实数会议和计算机,RNC7.

http://andrewthall.org/papers/df64_qf128.pdf Andrew Thall用于GPU计算的扩展精度浮点数.

  • +1与其他答案不同,这个实际上解决了OP的问题,并提供了与相关论文的非常好的链接. (9认同)

Nem*_*emo 10

这并不简单.

浮点数(IEEE 754单精度)具有1个符号位,8个指数位和23位尾数(好,有效24位).

双精度(IEEE 754双精度)具有1个符号位,11个指数位和52位尾数(实际上为53).

您可以使用其中一个浮点数的符号位和8个指数位,但是如何从另一个浮点数中获得3个指数位和29位尾数?

也许其他人可以想出一些聪明的东西,但我的回答是"这是不可能的".(或者至少,"不比使用64位结构和实现自己的操作更容易")

  • 使用 [float-float](https://en.wikipedia.org/wiki/Double-double_%28arithmetic%29#Double-double_arithmetic) 技术,他无法实现双精度范围和精度,但这远远超过浮点数并且比软件 double 快得多,以防万一只有硬件浮点运算,例如在旧的 CUDA 或 ARM CPU 的情况下 (3认同)

Mr *_*ooz 6

这取决于您想要执行的操作类型.如果您只关心加法和减法,Kahan Summation可能是一个很好的解决方案.


Mat*_*ery 5

如果您需要精度和宽范围,则需要双精度浮点的软件实现,例如SoftFloat.

(另外,基本原则是将每个值的表示(例如64位)分成三个组成部分 - 符号,指数和尾数;然后根据指数的差异移动一个部分的尾数,添加到或根据符号位从其他部分的尾数中减去,并可能通过移动尾数并相应地调整指数来重新归一化结果.一路上,有很多细节需要考虑,以避免不必要的损失准确性,并处理特殊值,如无穷大,NaNs和非规范化数字.)


wal*_*lyk 5

鉴于超过 23 个量级的高精度的所有限制,我认为最有效的方法是实现自定义算术包。

快速调查显示 Briggs 的doubledouble C++ 库应该可以满足您的需求,然后是一些。请参阅。[*] 默认实现基于double实现 30 位有效数字的计算,但很容易重写float以实现 13 或 14 位有效数字。如果注意隔离具有相似幅度值的加法运算,仅在最后的运算中将极端值加在一起,这可能足以满足您的要求。

不过请注意,评论中提到了对 x87 控制寄存器的混淆。我没有检查细节,但这可能会使代码对于您的使用来说太不可移植了。


[*] 那篇文章链接了 C++ 源代码,但只有 gzip 压缩的 tar 不是死链接。