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

标签 c++ floating-point

假设您正在编写一个执行大量浮点运算的 C++ 应用程序。假设此应用程序需要在合理范围内的硬件和操作系统平台(例如 32 位和 64 位硬件、32 位和 64 位版本的 Windows 和 Linux...)之间具有可移植性。

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

对于整数,我们有 stdint.h但似乎不存在等效的 float 。


[编辑]

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

对于整数,我可以这样写:

#include <stdint>
[...]
int32_t myInt;

并确保无论我使用何种(C99 兼容)平台,myInt 都是 32 位整数。

如果我写:

double myDouble;
float myFloat;

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

最佳答案

非 IEEE 754

一般来说,你不能。在一致性和性能之间总是存在权衡,C++ 将其交给您。

对于没有浮点运算的平台(如嵌入式处理器和信号处理处理器),您不能使用 C++“原生”浮点运算,至少不能移植。虽然软件层是可能的,但这对于此类设备来说肯定是不可行的。

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

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

IEEE 754 - 一致性

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

为什么结果会变得不一致? 首先,FPU 寄存器的分辨率通常高于 double 寄存器(例如 80 位),因此只要代码生成器不存储回值,中间值就会以更高的精度保存。

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

此外 - 我从艰难的方式学到的东西 - 打印和解析功能不一定跨平台一致,也可能是由于数字不准确。

float

浮点运算本质上比 double 运算快,这是一个常见的误解。通常仅通过较少的缓存未命中,处理大型 float 组会更快。

注意 float 精度。它可以在很长一段时间内“足够好”,但我经常看到它失败的速度比预期的要快。由于 SIMD 支持,基于 float 的 FFT 可以更快,但很早就为音频处理生成了显着的人工制品。

关于c++ - 如何在 C++ 中编写可移植的浮点运算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/982421/

相关文章:

c++ - 使用 QUdpSocket 作为 QIODevice 的正确方法是什么?

c++ - 有没有一种方法可以使用 catch 框架来比较流或文件?

c++ - 数组中值的快速乘法

C++ Linux 命名管道卡在 open() 与 O_WRONLY

c - 在范围内定义用户输入

java - 这三个特殊的浮点值是什么意思 : positive infinity, 负无穷大,NaN?

javascript - JavaScript 数字文字中的指数语法 (1e2) 是 IEEE 754 规范的一部分吗?

javascript - 对浮点相等性测试感到困惑?

c++ - 为什么 printf 和 isnan 不同意 long double 值是否为 NaN?

c++ - std 类型别名的自定义点