C++11中的std::nearbyint和std::round有何区别?

15

C++11 引入了 std::nearbyintstd::round 函数。两者都返回“最近”的整数值。

什么时候应该使用其中的一种?

我已经使用值为 0.5 进行了测试:

案例1 : nearbyint演示

#include <iostream>
#include <cmath>

int main()
{
    std::cout<<"nearbyint(0.5) = "<<std::nearbyint(0.5);
}

输出:0

情况2:round的演示

#include <iostream>
#include <cmath>

int main()
{
    std::cout<<"round(0.5) = "<<std::round(0.5);
}

输出:1

为什么这两个输出不同呢?

2个回答

24

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


7
正如Ron的回答所指出的那样,其中一个区别在于rint()nearbyint()一方面,以及round()另一方面,是后者使用固定的舍入模式,不管当前生效的动态舍入模式如何。这方面的细节无法在2011年的ISO C++标准中找到,在第26.8 C库[c.math]中仅指向C标准。1999年的ISO C标准将round()的操作规定如下:

7.12.9.6 [...] 舍入函数将其参数四舍五入为浮点格式中最近的整数值,将一半的情况远离零进行舍入,而不考虑当前的舍入方向。

round()使用的特定舍入模式列在IEEE 754(2008)浮点标准的第4.3.1节中,称为roundTiesToAway,意味着平局情况被舍入远离零。但是FE_TONEAREST的通常绑定是IEEE-754(2008)舍入模式roundTiesToEven,这意味着这些平局情况舍入为偶数。事实上,这是我在使用支持fesetround()的众多系统平台中遇到的唯一FE_TONEAREST实现。
这两种“最近”舍入的处理差异在提问者的示例中很明显:0.5在使用round()时会四舍五入到更大(在数量级上)的整数(1),但在使用nearbyint()rint()时会舍入为偶数(0)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接