【发布时间】:2015-12-21 04:21:15
【问题描述】:
C 标准库在 C99 中提供了 round、lround 和 llround 系列函数。但是,这些函数不符合 IEEE-754 标准,因为它们没有按照 IEEE 的要求实现半对偶的“银行家四舍五入”。如果小数部分正好是 0.5,则半到偶数舍入要求将结果舍入到最接近的偶数值。正如cppreference.com 中所述,C99 标准要求从零开始一半
1-3) 计算最接近 arg 的整数值(以浮点格式),从零开始舍入一半的情况,而不管当前的舍入模式。
在 C 中实现舍入的常用方式是表达式 (int)(x + 0.5f),尽管它在严格的 IEEE-754 数学中是 incorrect,但通常由编译器翻译成正确的 cvtss2si 指令。但是,这当然不是一个可移植的假设。
如何实现一个函数,该函数将使用半偶数语义舍入任何浮点值?如果可能,该函数应该只依赖于语言和标准库语义,以便它可以对非 IEEE 浮点类型进行操作。如果这是不可能的,那么根据 IEEE-754 位表示定义的答案也是可以接受的。请用<limits.h> 或<limits> 来描述任何常量。
【问题讨论】:
-
它们符合标准,但没有全部实现。 “四舍五入,远离零”是 IEEE-754 舍入模式之一。
-
IEEE-754 指出存在教科书舍入模式,但仅适用于十进制浮点数。
An implementation of this standard shall provide roundTiesToEven and the three directed rounding attributes. A decimal format implementation of this standard shall provide roundTiesToAway as a userselectable rounding-direction attribute. The rounding attribute roundTiesToAway is not required for a binary format implementation.将关系四舍五入到偶数是唯一可移植(且合理)的模式。 -
而不是
round(),请查看rint(),默认舍入模式为“舍入到最接近或偶数”。 -
您可能对 CPython 的解决方案感兴趣,here。
-
@njuffa 非常感谢指向
rint(非常不直观的名称)的指针。我不得不仔细检查 C 标准,但是当设置__STDC_IEC_559__时,它似乎确实做了正确的事情。真正的谜团是为什么round做的事情与rint和FE_TONEAREST不同。
标签: c++ c floating-point ieee-754 bankers-rounding