我需要一个简单的浮点舍入函数,这样:

double round(double);

round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1

我可以在math.h中找到ceil()和floor() -但没有round()。

它是否以另一个名字出现在标准c++库中,或者它是否丢失了??


当前回答

如果你最终想要将round()函数的双输出转换为int型,那么这个问题的可接受的解决方案将如下所示:

int roundint(double r) {
  return (int)((r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5));
}

当传入均匀随机值时,在我的机器上大约为8.88 ns。

据我所知,下面的功能是等效的,但在我的机器上是2.48 ns,具有显著的性能优势:

int roundint (double r) {
  int tmp = static_cast<int> (r);
  tmp += (r-tmp>=.5) - (r-tmp<=-.5);
  return tmp;
}

性能更好的原因之一是跳过了分支。

其他回答

编者注:下面的答案提供了一个简单的解决方案,其中包含几个实现缺陷(参见Shafik Yaghmour的答案以获得完整的解释)。注意,c++ 11已经将std::round、std::lround和std::llround作为内置程序。

c++ 98标准库中没有round()。不过你可以自己写。下面是round-half-up的实现:

double round(double d)
{
  return floor(d + 0.5);
}

c++ 98标准库中没有循环函数的可能原因是它实际上可以以不同的方式实现。以上是一种常见的方法,但还有其他的方法,如四舍五入到偶数,如果你要做很多四舍五入,这种方法的偏差更小,通常更好;不过实现起来有点复杂。

你可以四舍五入到n位精度:

double round( double x )
{
const double sd = 1000; //for accuracy to 3 decimal places
return int(x*sd + (x<0? -0.5 : 0.5))/sd;
}

我在asm的x86架构和MS VS特定的c++中使用round的以下实现:

__forceinline int Round(const double v)
{
    int r;
    __asm
    {
        FLD     v
        FISTP   r
        FWAIT
    };
    return r;
}

UPD:返回双值

__forceinline double dround(const double v)
{
    double r;
    __asm
    {
        FLD     v
        FRNDINT
        FSTP    r
        FWAIT
    };
    return r;
}

输出:

dround(0.1): 0.000000000000000
dround(-0.1): -0.000000000000000
dround(0.9): 1.000000000000000
dround(-0.9): -1.000000000000000
dround(1.1): 1.000000000000000
dround(-1.1): -1.000000000000000
dround(0.49999999999999994): 0.000000000000000
dround(-0.49999999999999994): -0.000000000000000
dround(0.5): 0.000000000000000
dround(-0.5): -0.000000000000000

如果你最终想要将round()函数的双输出转换为int型,那么这个问题的可接受的解决方案将如下所示:

int roundint(double r) {
  return (int)((r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5));
}

当传入均匀随机值时,在我的机器上大约为8.88 ns。

据我所知,下面的功能是等效的,但在我的机器上是2.48 ns,具有显著的性能优势:

int roundint (double r) {
  int tmp = static_cast<int> (r);
  tmp += (r-tmp>=.5) - (r-tmp<=-.5);
  return tmp;
}

性能更好的原因之一是跳过了分支。

它在cmath中从c++ 11开始提供(根据http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)

#include <cmath>
#include <iostream>

int main(int argc, char** argv) {
  std::cout << "round(0.5):\t" << round(0.5) << std::endl;
  std::cout << "round(-0.5):\t" << round(-0.5) << std::endl;
  std::cout << "round(1.4):\t" << round(1.4) << std::endl;
  std::cout << "round(-1.4):\t" << round(-1.4) << std::endl;
  std::cout << "round(1.6):\t" << round(1.6) << std::endl;
  std::cout << "round(-1.6):\t" << round(-1.6) << std::endl;
  return 0;
}

输出:

round(0.5):  1
round(-0.5): -1
round(1.4):  1
round(-1.4): -1
round(1.6):  2
round(-1.6): -2