C/C++:IEEE 754 float addition/multiplication/... 和 int-to-float 转换是否标准化?

C/C++: Are IEEE 754 float addition/multiplication/... and int-to-float conversion standardized?

示例:

#include <math.h>
#include <stdio.h>

int main()
{
    float f1 = 1;
    float f2 = 4.f * 3.f;
    float f3 = 1.f / 1024.f;
    float f4 = 3.f - 2.f;
    printf("%a\n",f1);
    printf("%a\n",f2);
    printf("%a\n",f3);
    printf("%a\n",f4);
    return 0;
}

gcc/clang 上的预期输出:

0x1p+0
0x1.8p+3
0x1p-10
0x1p+0

正如所见,结果看起来“合理”。但是,可能有多种不同的方式 显示这些数字。或者显示非常接近的数字。

在 C 和 C++ 中是否保证 IEEE 754 浮点运算(如加法、乘法和整数到浮点数的转换)在所有机器和所有编译器上产生相同的结果(即生成的浮点数都是位-wise 相等)?

否,除非定义宏__STD_IEC_559__

基本上该标准不需要 IEEE 754 兼容浮点,因此大多数编译器将使用硬件提供的任何浮点支持。如果硬件提供 IEEE 兼容的浮点数,大多数针对该目标的编译器将使用它并预定义 __STD_IEC_559__ 宏。

如果定义了宏,那么IEEE 754保证floatdouble的位表示(但不是字节顺序)为32位和64位IEEE 754。这在turn 保证 bit-exact 表示 double 算术(但请注意,C 标准允许 float 算术以 32 位或 64 位精度发生)。

C 标准要求如果结果在结果类型的范围内,则 float 到 int 的转换与 trunc 函数相同,但不幸的是 IEEE 并没有真正定义函数的行为,只是的基本算术。 C 规范还允许编译器重新排序操作违反 IEEE754(这可能会影响精度),但大多数支持 IEEE754 的人不会在没有命令行选项的情况下这样做。

轶事证据还表明,一些编译器没有定义宏,即使它们应该定义宏,而其他编译器在不应该定义宏时定义它(不严格遵循 IEEE 754 的所有要求)。这些情况可能应该被视为编译器错误。

Is it guaranteed in C and in C++ that IEEE 754 floating arithmetic like addition, multiplication and int-to-float conversion yield the same results, on all machines and with all compilers (i.e. that the resulting floats are all bit-wise equal)?


如果异常编译器定义了_STDC_IEC_559__,那么几乎是.

An implementation that defines STDC_IEC_559 shall conform to the specifications in this annex.
C17dr Annex F (normative) IEC 60559 floating-point arithmetic

IEEE 754 浮点运算,如加法、乘法和 int-to-float 转换产生与 _FLT_EVAL_METHOD_ == 0 类似的结果。当 _FLT_EVAL_METHOD_ > 0 时,更广泛的浮点数学可能会用于导致不同结果的许多操作。然而,即使使用 _FLT_EVAL_METHOD_ == 0,我也怀疑 所有 FP 代码是否会计算出完全相同的结果。

对于高度可移植的 FP 代码,应该有变异容差。


OP 也在寻找 bit-wise 等价物。 FP 也有端序问题,因此 2 种实现可以满足所有 IEEE 754 标准,但端序不同。

意识到 C 和 C++ 标准都力求包含不寻常的体系结构。他们永远不会强制要求严格遵守 IEEE-754。

还意识到使用 IEEE-754 的系统将依赖处理器架构来正确实现它。那么您的实际问题是处理器如何符合 IEEE-754 规则,这很难得到权威的回答。 Intel Pentium famously had a bug 为一小部分操作产生了错误的结果。

我不知道整数到浮点数的转换是否像其他操作一样严格指定,但我怀疑是这样。一个 32 位 IEEE-754 浮点数有 24 位尾数,因此可以保存任何 24 位整数而不损失精度。那将是从 -16777216 到 16777216 的范围。我会对任何无法 100% 可靠地执行操作的实现感到非常失望。在该范围之外,存在无法表示的整数浮点值,因此应应用舍入来确定最终值。例如,2147483520 和 2147483648 之间没有有效的浮点数,那么如果您尝试转换 2147483583 或 2147483585 会发生什么?老实说,我不知道结果会是什么,也不知道结果是否正确。