由于需要检查和正确处理许多边缘情况,软件仿真的IEEE浮点数/双精度数很慢。
- 输入中的+/-无穷大
- 输入中的不是数字
- 输入中的+/-0
- 规格化与非规格化数字以及尾数中的隐含“1”
- 解包和打包
- 规格化/非规格化
- 下溢和上溢检查
- 正确舍入,这可能导致额外的(去)规范化和/或下溢/上溢
如果您只是粗略地计算上述原始微操作的数量(每个列表项为1),则会接近10。在最坏的情况下,还会有更多。
因此,如果您对符合IEEE标准的浮点运算感兴趣,请预期每个仿真操作都比其整数对应物慢约30倍(CodesInChaos的评论及时提到了每次加法/乘法38个时钟)。
您可以通过选择以下浮点格式来简化一些问题:
- 仅一个零
- 没有不是数字
- 仅规格化数字
- 尾数中没有隐含“1”
- 指数和尾数各占用整数个字节
- 没有或原始舍入
- 可能没有无穷大
- 可能是2的补码尾数
- 可能没有指数偏移
定点算术可能更具性能。但通常问题在于您必须预先知道所有输入和中间结果的范围,以便选择正确的格式以避免溢出。您还可能需要支持许多不同的定点格式,例如16.16、32.32、8.24、0.32。 C++模板可以帮助减少代码重复。
无论如何,您所能做的最好的事情就是定义您的问题,使用浮点和定点算术解决它,观察哪个适用于哪个CPU,并选择获胜者。
编辑:有关更简单的浮点格式的示例,请查看MIL-STD-1750A的32位浮点格式:
MSB LSB MSB LSB
------------------------------------------------------------------
| S| Mantissa | Exponent |
------------------------------------------------------------------
0 1 23 24 31
浮点数表示为分数幂次方和2的乘积。在浮点操作开始时,所有浮点数被假定为归一化或浮点零,所有浮点操作的结果都会进行归一化(一个归一化的浮点数具有幂次方的符号和相反值的下一个位)或浮点零。浮点零定义为0000 0000
16即幂次方和分数均为零的数(00
16)。扩展浮点零定义为0000 0000 0000
16,即幂次方和分数均为零。以下是32位浮点数机器表示的一些例子:
十进制数 十六进制符号
(分数 x 幂次方)
0.9999998 x 2127 7FFFFF 7F
0.5 x 2127 400000 7F
0.625 x 24 500000 04
0.5 x 21 400000 01
0.5 x 20 400000 00
0.5 x 2-1 400000 FF
0.5 x 2-128 400000 80
0.0 x 20 000000 00
-1.0 x 20 800000 00
-0.5000001 x 2-128 BFFFFF 80
-0.7500001 x 24 9FFFFF 04