在C++中舍入到最近偶数

Blu*_*pud 3 int rounding

我想知道C++是否包含了一种舍入到最接近的偶数的方法.我环顾四周,似乎无法找到关于这个主题的任何内容.我可以编写自己的方法,但使用内置方法很可能会更快.

谢谢.

Phe*_*ost 8

如前所述,没有内置方法。那么让我们看看有几种方法可以做到这一点。但首先...

性能注意事项:

  • 避免除法,因为它对于浮点数来说仍然很慢,尽管不像对于整数那么糟糕。浮点数的乘法几乎与加法一样快。
  • 对于任何整数 x乘以 2 -x保证等于除以 2 x,同时不会损失精度。
  • 将所有常量设置为相同类型以防止升级,尤其是当该值将再次存储为相同类型时。

简单的

std::round( x * 0.5f ) * 2.0f

这将在每个奇数处从零舍入,从而产生一个小的偏差。

一般来说,std::round尽可能避免。它很慢,因为它必须:保存舍入模式,切换它,舍入,然后恢复以前的舍入模式。所有这些都是为了引入偏见。

神奇数字

在 C++11 之前,我们可以使用幻数通过内置银行家舍入来减轻偏差。警告:这依赖于默认的舍入模式 ( FE_TONEAREST),通常在 99.9999% 的情况下都是如此,但要警惕其他库可能会更改它并且之后不会恢复它。

float魔法:( x + 25165824f ) - 25165824f

这利用了浮点精度只有这么多位的事实。通过添加足够大的幻数,我们不想要的最低位将自动舍入,之后我们减去幻数,使原始数舍入到正确的精度。

幻数计算为 1.5 * 2 p,其中p是浮点有效数的精度: 为 24 float, 为 53 double, 为 64 long double。在我们的一点帮助下,std::numeric_limits我们可以使其通用。

template< typename T >
T magic_round_to_even( T x ) {
  static T magic = 1.5 * std::pow( 2.0L, std::numeric_limits< T >::digits);
  return ( x + magic ) - magic;
}
Run Code Online (Sandbox Code Playgroud)

通过改变我们的幻数p ,我们可以四舍五入到不同的 2 的幂。p - 1 将创建标准银行家四舍五入。

C++11

所有人都欢呼新的舍入方式:std::nearbyint。这遵循当前的舍入模式,因此如果舍入模式被其他东西弄乱了,我们可以使用std::fesetround它来将其恢复为FE_TONEAREST.

std::nearbyint( x * 0.5f ) * 2.0f

这与第一个版本一样直观,但没有任何偏见。


Gre*_*ill 6

没有内置函数来执行此操作.最简单的方法可能是做一些事情:

even = round(x / 2) * 2;
Run Code Online (Sandbox Code Playgroud)