std::nearbyint vs std::round in C++11

std::nearbyint vs std::round in C++11

本文关键字:std C++11 in vs nearbyint round      更新时间:2023-10-16

C++11引入了std::nearint和std::round函数。两者都返回"最近"整数值。

我应该在何时何地选择其中一种?

我已经用0.5的值测试了它们:

案例 1: 附近 int 的演示

#include <iostream>
#include <cmath>
int main()
{
std::cout<<"nearbyint(0.5) = "<<std::nearbyint(0.5);
}

输出:0

案例2:回合演示

#include <iostream>
#include <cmath>
int main()
{
std::cout<<"round(0.5) = "<<std::round(0.5);
}

输出:1

为什么输出不同?

std::round函数忽略当前的舍入模式,而std::nearbyint会将其考虑在内。您可以更改舍入模式:

#include <cfenv>
int main() {
std::fesetround(FE_UPWARD);
// perform calculations
std::fesetround(FE_DOWNWARD);
// perform calculations
// other rounding methods...
}

并观察不同的结果。要获取当前的舍入模式值,请使用 std::fegetround() 函数。默认值(已定义的实现)值可能0转换为FE_TONEAREST

正如 Ron在回答中指出的那样,rint()nearbyint()round()之间的一个区别是,后者使用固定舍入模式,而不管当前有效的动态舍入模式如何。在 2011 ISO C++ 标准中找不到这方面的细节,该标准在第26.8 C 库 [c.math]节中仅指向 C 标准。1999 ISO C 标准规定了round()的操作如下:

7.12.9.6[...]round 函数将其参数舍入为浮点格式中最接近的整数值,将大小写四舍五入到一半 从零开始,无论当前舍入方向如何。

round()使用的特定舍入模式在IEEE 754(2008)浮点标准的第4.3.1节中列为roundTiesToAway,这意味着平局情况从零四舍五入。但是通常的绑定FE_TONEAREST是IEEE-754(2008)舍入模式roundTiesToEven,这意味着这样的平局情况四舍五入为偶数。实际上,这是我在我使用的众多系统平台上遇到的唯一FE_TONEAREST实现,该支持fesetround()

在提问者的例子中,这两种舍入"到最近"变体的处理差异是显而易见的:当使用round()时,0.5舍入到下一个较大的(量级)整数(1),但是当使用nearbyint()rint()时,它会舍入到偶数(0)。