round() for float in C++

后端 未结 22 1206
时光取名叫无心
时光取名叫无心 2020-11-22 03:01

I need a simple floating point rounding function, thus:

double round(double);

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

I can find

相关标签:
22条回答
  • 2020-11-22 03:34

    It's available since C++11 in cmath (according to 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;
    }
    

    Output:

    round(0.5):  1
    round(-0.5): -1
    round(1.4):  1
    round(-1.4): -1
    round(1.6):  2
    round(-1.6): -2
    
    0 讨论(0)
  • 2020-11-22 03:34

    Boost offers a simple set of rounding functions.

    #include <boost/math/special_functions/round.hpp>
    
    double a = boost::math::round(1.5); // Yields 2.0
    int b = boost::math::iround(1.5); // Yields 2 as an integer
    

    For more information, see the Boost documentation.

    Edit: Since C++11, there are std::round, std::lround, and std::llround.

    0 讨论(0)
  • 2020-11-22 03:34

    Beware of floor(x+0.5). Here is what can happen for odd numbers in range [2^52,2^53]:

    -bash-3.2$ cat >test-round.c <<END
    
    #include <math.h>
    #include <stdio.h>
    
    int main() {
        double x=5000000000000001.0;
        double y=round(x);
        double z=floor(x+0.5);
        printf("      x     =%f\n",x);
        printf("round(x)    =%f\n",y);
        printf("floor(x+0.5)=%f\n",z);
        return 0;
    }
    END
    
    -bash-3.2$ gcc test-round.c
    -bash-3.2$ ./a.out
          x     =5000000000000001.000000
    round(x)    =5000000000000001.000000
    floor(x+0.5)=5000000000000002.000000
    

    This is http://bugs.squeak.org/view.php?id=7134. Use a solution like the one of @konik.

    My own robust version would be something like:

    double round(double x)
    {
        double truncated,roundedFraction;
        double fraction = modf(x, &truncated);
        modf(2.0*fraction, &roundedFraction);
        return truncated + roundedFraction;
    }
    

    Another reason to avoid floor(x+0.5) is given here.

    0 讨论(0)
  • 2020-11-22 03:34

    If you ultimately want to convert the double output of your round() function to an int, then the accepted solutions of this question will look something like:

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

    This clocks in at around 8.88 ns on my machine when passed in uniformly random values.

    The below is functionally equivalent, as far as I can tell, but clocks in at 2.48 ns on my machine, for a significant performance advantage:

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

    Among the reasons for the better performance is the skipped branching.

    0 讨论(0)
提交回复
热议问题