首页 > 解决方案 > C 标准的 FE_TONEAREST 舍入模式是否保证中间关系舍入为偶数?

问题描述

我正在编写依赖于 C(特别是 c11)四舍五入到偶数的中途关系的代码。当将带有舍入模式的 rint 用作 FE_TONEAREST 时,我没有在 C 标准中找到说明如何使用 FE_NEAREST 处理关系的保证。ISO C 标准的第 509 页指出

<fenv.h> 中的 fegetround 和 fesetround 函数提供了在由 <fenv.h> 中的舍入方向宏(FE_TONEAREST、FE_UPWARD、FE_DOWNWARD、FE_TOWARDZERO)和值 0、1 表示的 IEC 60559 定向舍入模式中进行选择的工具FLT_ROUNDS 的 、 2 和 3 是 IEC 60559 有向舍入模式。

但是,我在 IEC 60559 标准中找不到任何有关舍入模式的文档。在我的测试机器上,行为是在 FE_TONEAREST 中,关系四舍五入到偶数,我想确保这是由 c11 标准强制执行的,而不是实现定义的。

标签: clanguage-lawyerroundingc11fenv

解决方案


C11 附件 F 在 §F.1 中说:

IEC 60559 浮点标准专门用于微处理器系统的二进制浮点运算,第二版 (IEC 60559:1989) [...]

然后,在 §F.3,第 1 段(正如您在问题中已经引用的那样):

<fenv.h> 中的 fegetround 和 fesetround 函数提供了在由 <fenv.h> 中的舍入方向宏(FE_TONEAREST、FE_UPWARD、FE_DOWNWARD、FE_TOWARDZERO)和值 0、1 表示的 IEC 60559 定向舍入模式中进行选择的工具FLT_ROUNDS 的 、 2 和 3 是 IEC 60559 有向舍入模式。

(注意:准确地说,我正在查看 C11 标准的公开 N1570 最终草案,但我的理解是它与最终标准基本相同。)

因此,此处对 IEC 60559 的引用实际上是对(现已两次取代的)IEC 60559:1989 标准的引用。我无法访问那个精确的标准,但我确实有一份 IEEE 754-1985,而且我相信这两个标准(IEC 60559:1989 和 IEEE 754-1985)的内容应该基本相同,尽管我观察到各个标准的目录中至少存在大小写差异。(感谢Michael Burr在评论中确认标准在实质上是相同的,如果不是逐字相同的话。)

IEEE 754-1985 在第 4 节中定义了四种舍入模式,称为“舍入到最近”、“向 +∞ 舍入”、“向 -∞ 舍入”和“向零舍入”。后三个被描述为“定向舍入模式”。对于“四舍五入”,我们在 §4.1 中有以下文字:

如果两个最接近的可表示值同样接近,则应传递其最低有效位为零的值

换句话说,它是在描述圆圆的平局。(IEEE 754 标准的后期版本为上述舍入模式引入了名称“roundTiesToEven”、“roundTowardPositive”、“roundTowardNegative”和“roundTowardZero”(现在称为“属性”而不是“模式”,我相信因为“模式”暗示某种持久的环境设置),并定义第五个舍入属性“roundTiesToAway”。但 C11 明确表示它指的是该标准的早期版本。)

现在由于 C11 没有使用与 IEEE 754-1985 完全相同的术语,因此我们可以推断上述四种舍入模式依次对应于“FE_TONEAREST”、“FE_UPWARD”、“FE_DOWNWARD”和“FE_TOWARDZERO” ,但似乎没有任何理由怀疑这是预期的匹配。所以假设__STDC_IEC_559__是定义的,FE_TONEAREST 确实应该对应于“roundTiesToEven”。Nate Eldredge关于 C2x 的评论进一步强化了这是预期的匹配。

所以总而言之,很明显(至少对我而言)意图是,当__STDC_IEC_559__定义时,舍入模式FE_TONEAREST应对应于“舍入到最近”,在 IEEE 754 标准的后续版本中命名为“roundTiesToEven”。当然,C 的实现在多大程度上尊重这种意图是一个单独的问题(但我希望他们中的绝大多数都这样做)。


推荐阅读