使用 2 "float" 秒模拟"double"
Emulate "double" using 2 "float"s
我正在为只支持32位单精度浮点运算的嵌入式硬件编写程序。然而,我正在实现的算法需要64位双精度加法和比较。我试图使用两个float
的元组来模拟double
数据类型。因此,double d
将被模拟为包含以下元组的struct
: (float d.hi, float d.low)
。
使用字典顺序进行比较应该很简单。然而,添加有点棘手,因为我不确定我应该使用哪个基础。应该是FLT_MAX
吗?我怎样才能发现进位?
如何做到这一点?
Edit (clear):我需要额外的有效数字而不是额外的范围。
double-float是一种技术,它使用一对单精度数字来实现几乎是单精度算术精度的两倍,同时稍微缩小单精度指数范围(由于范围远端的中间下溢和溢出)。基本算法是由T.J. Dekker和William Kahan在20世纪70年代开发的。下面我列出了两篇最近的论文,它们展示了这些技术如何适用于gpu,然而,这些论文中涵盖的大部分材料都是独立于平台的,因此应该对手头的任务有用。
https://hal.archives - ouvertes.fr/hal 00021443纪尧姆·达·格拉帕拉,大卫·德福图形硬件上浮点-浮点运算符的实现第7届实数与计算机会议,RNC7.
http://andrewthall.org/papers/df64_qf128.pdf安德鲁ThallGPU计算的扩展精度浮点数。
这可不简单。
一个浮点数(IEEE 754单精度)有1个符号位,8个指数位和23个尾数位(实际上是24个)。
双精度(IEEE 754双精度)有1个符号位,11个指数位和52个尾数位(有效值为53)。
你可以从你的一个浮点数中使用符号位和8个指数位,但是你如何从另一个浮点数中获得3个指数位和29个尾数?
也许其他人可以想出一些聪明的办法,但我的答案是"这是不可能的"。(或者至少,"不比使用64位结构体并实现自己的操作更容易")
这在一定程度上取决于您想要执行的操作类型。如果你只关心加减法,卡汉求和是一个很好的解决方案。
如果您既需要精度又需要大范围,则需要双精度浮点数的软件实现,例如SoftFloat。
(此外,基本原理是将每个值的表示(例如64位)分解为它的三个组成部分-符号,指数和尾数;然后根据指数的差异移动一部分的尾数,根据符号位对另一部分的尾数进行加减,并可能通过移动尾数并相应地调整指数来重新规范化结果。在此过程中,有许多繁琐的细节需要考虑,以避免不必要的精度损失,并处理特殊值,如无穷大,nan和非规范化数字。
给定超过23个数量级的高精度的所有约束,我认为最有效的方法是实现自定义算术包。
一个快速调查显示Briggs的doubledouble c++库应该满足你的需求。看到这个。[*]默认实现是基于double
来实现30位有效数字的计算,但很容易重写为使用float
来实现13或14位有效数字。这可能足以满足您的需求,如果小心地隔离具有相似大小值的加法操作,只在最后的操作中将极值加在一起。
要注意,注释提到了混淆x87控制寄存器。我没有检查细节,但这可能会使代码太不可移植,不适合您使用。
[*]这篇文章链接了c++源代码,但只有压缩后的tar文件不是死链接。
这类似于许多编译器在一些只支持硬件double
计算的机器上对long double
使用的双双算法。它也被用作没有double
支持的旧NVIDIA gpu上的float-float。参见在GPU上用2个FP32仿真FP64。这样计算将比软件浮点库快得多。
然而,在大多数微控制器中,没有硬件支持float
s,因此它们纯粹在软件中实现。正因为如此,使用float-float
可能会而不是提高性能,并引入一些内存开销来节省额外的指数字节。
如果您确实需要更长的尾号,请尝试使用自定义浮点库。您可以选择任何对您来说足够的东西,例如,如果只需要40位尾数和7位指数,则更改库以适应您自己的新的48位浮点类型。不需要花时间计算/存储不必要的16位了。但是这个库应该非常高效,因为编译器的库通常对自己的float类型进行汇编级优化。
另一个可能有用的基于软件的解决方案:GNU MPFR
它处理了许多其他特殊情况,并允许任意精度(优于64位双精度),否则您必须自己处理。
这是不实际的。如果是这样,每个嵌入式32位处理器(或编译器)都会通过这样做来模拟双精度。据我所知,目前还没有人这样做。大多数只是用float
代替double
。
如果你需要的是精度而不是动态范围,你最好的选择是使用定点。如果编译器支持64位,这也会更容易。
- 如何使用Google Mock来模拟gettimeofday()
- G锁定铸造到基础上会释放模拟行为
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 落砂模拟碰撞检测C++和SFML
- 在gtest.中使用fff.h模拟系统API
- C++在数学计算中将double转换为int
- 谷歌模拟和覆盖关键字
- 用C#中的并集模拟C++嵌套结构
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 在c++中为double类型的数组创建一个unique_ptr
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- vector<vector<double>> to mxArray using memcpy
- (double) 和 double() 之间的区别
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- 如何模拟不同边数的骰子滚动?
- C++ Version Of Double.longBitsToDouble
- 模拟持久按键
- 使用SIR模型的疾病爆发模拟
- 使用 2 "float" 秒模拟"double"