如何在c ++中编写可移植的浮点运算?

Sté*_*iez 8 c++ floating-point

假设您正在编写一个执行大量浮点运算的C++应用程序.假设这个应用程序需要在合理范围的硬件和操作系统平台上可移植(例如32位和64位硬件,Windows和Linux都是32位和64位版本......).

您如何确保所有平台上的浮点算法都相同?例如,如何确保所有平台上的32位浮点值真的是32位?

对于整数,我们有stdint.h但似乎没有浮点等价物.


[编辑]

我得到了非常有趣的答案,但我想为这个问题增加一些精确度.

对于整数,我可以写:

#include <stdint>
[...]
int32_t myInt;
Run Code Online (Sandbox Code Playgroud)

并确保无论我在哪个(C99兼容)平台上,myInt都是32位整数.

如果我写:

double myDouble;
float myFloat;
Run Code Online (Sandbox Code Playgroud)

我确定这会在所有平台上分别编译为64位和32位浮点数吗?

pet*_*hen 9

非IEEE 754

一般来说,你不能.在一致性和性能之间总是需要权衡,而C++会为您提供帮助.

对于没有浮点运算的平台(如嵌入式和信号处理处理器),您不能使用C++"本机"浮点运算,至少不能这样.虽然软件层是可能的,但对于这种类型的设备来说肯定是不可行的.

对于这些,您可以使用16位或32位定点算法(但您甚至可能会发现只支持基本的长 - 而且通常,div非常昂贵).然而,这将比内置的定点算术慢得多,并且在基本的四个操作之后变得很痛苦.

我没有遇到过支持不同于IEEE 754格式的浮点的设备.根据我的经验,您最好的选择是希望达到标准,否则您通常最终会围绕设备的功能构建算法和代码.当sin(x)突然花费1000倍时,你最好选择一个不需要它的算法.

IEEE 754 - 一致性

我在这里发现的唯一不可移植性是当你期望跨平台的结果相同时.最大的影响是优化者.同样,您可以交换准确性和速度以保持一致性.大多数编译器都有一个选项 - 例如Visual C++中的"浮点一致性".但请注意,这总是超出标准保证的准确性.

为什么结果不一致? 首先,FPU寄存器通常具有比double(例如80位)更高的分辨率,因此只要代码生成器不将值存储回来,就可以以更高的精度保持中间值.

其次,a*(b+c) = a*b + a*c由于精度有限,等价不精确.尽管如此,优化器(如果允许)可以使用它们.

此外 - 我学到了很多困难 - 打印和解析功能在各个平台上不一定一致,可能也是由于数字不准确.

浮动

一种常见的误解是,浮动操作本质上比双重更快.通过单独减少缓存未命中,处理大型浮点数组的速度更快.

浮动精度要小心.它可以在很长一段时间内"足够好",但我经常看到它失败的速度比预期的要快.由于支持SIMD,基于浮点数的FFT可以更快,但是在音频处理的早期阶段就会产生显着的假象.