C: 浮点运算的结果总是规范化的吗?

C: Is the result of floating point arithmetic ALWAYS normalized?

我对这些事情很好奇:

  1. C语言中的浮点数是不是总是以规范化的形式存储的? (也就是说,是否始终应用归一化?)
  2. 经过一些算术运算(加法、乘法)后得到的结果也是这样吗?
  3. 是否取决于语言或硬件 - FPU?

如果您能引用任何来源,那将非常有帮助。我查看了 IEEE-754 文档,但找不到任何关于实现的具体说明。

编辑:采用 IEEE-754 规范

Does the C language always store the floating-point numbers in the normalized form?

“视情况而定。”正如我们将看到的,决定这一点的是硬件而不是 C 语言。

如果实现使用的不是 IEEE-754,我们就没什么可说的了。

如果实现确实使用了 IEEE-754,那么所有数字总是被规范化存储,除了那些不是,即 subnormals.

Does this also hold true for the results obtained after some arithmetic (addition, multiplication)?

是的。 (更多内容见下文。)

Is it dependent on the language or the hardware - FPU?

它通常取决于硬件。大多数情况下,假设目标处理器完全支持浮点,C 程序会直接编译为本机浮点指令,而无需任何语言或编译器强加的额外处理。 (这与 Java 形成对比,后者确实具有语言强加的浮点定义,部分由 JVM 实现。)

C 标准确实有一个可选部分“附件 F”,它指定了一组特定的浮点行为,符合 IEEE-754。

现在,如果 C 实现采用附件 F 并符合 IEEE-754(通常是因为底层硬件也是),您前两个问题的答案变为更容易。在 IEEE-754 二进制算法中,除了一个例外,表示没有歧义。每个可以用规范化形式表示的数字都只有一个规范化表示。每个不能以规范化形式表示但可以表示为次正规形式的数字都只有一个次正规表示形式。这些约束适用于每个 IEEE-754 浮点数,包括(很自然地)其他操作的结果。

(正如 Eric 和 Chux 在评论中提醒我的那样,例外是零,IEEE-754 有两个,正负。)

所以“结果总是归一化吗?”的答案是“否”(因为 IEEE-754 肯定有那些次正规,当然还有零),但如果问题是“每个数字都有唯一的表示吗?”,答案大多是“是”。 (同样,零除外。或者如果您是少数使用 IEEE-754-2008 decimal 格式的人之一,这些格式的独特性要小得多。)请参阅还有 How to distinguish between 1 and zero floating-point values?

我想最后一个问题是“有多少 C 实现采用了附件 F?”,或者换句话说,“有多少处理器符合 IEEE-754?”对于通用计算机(大型机和个人计算机)上的CPU,据我所知这些天的答案是“所有这些”。另一方面,GPU 故意与 IEEE-754 不太兼容(因为它们可以以这种方式更加高效)。微处理器,对于“嵌入式”工作,我不太确定。 (通常他们根本没有可行的浮点数。)

It would be really helpful if you can cite any sources.

C 2018 5.2.4.2.2 3 定义了数字x的浮点表示为x = sbe Σ1≤=kp fkbk,其中s是符号(±1) , b 是基数,e 是整数指数,范围从 eminemax,p是精度(base- b位),和fk为基数-b 有效位数。

然后第 4 段说:

In addition to normalized floating-point numbers (f1 > 0 if x ≠ 0), floating types may be able to contain other kinds of floating-point numbers, such as subnormal floating-point numbers (x ≠ 0, e = emin, f1 = 0) and unnormalized floating-point numbers (x ≠ 0, e > emin, f1 = 0), and values that are not floating-point numbers, such as infinities and NaNs…

就是这样;除了附件 F 提供了对 IEC 60559(实际上是 IEEE 754)的可选绑定之外,C 标准对浮点数的规范化保持沉默。所以这回答了问题:

Does the C language always store the floating-point numbers in the normalized form? (That is, is the normalization always applied?)

没有

Does this also hold true for the results obtained after some arithmetic (addition, multiplication)?

没有

Is it dependent on the language or the hardware - FPU?

这取决于每个 C 实现。 C 实现可能受硬件影响或可能采用浮点运算的软件实现。