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 ceil()
and floor()
in the math.h - but not round()
.
Is it present in the standard C++ library under another name, or is it missing??
If you ultimately want to convert the
double
output of yourround()
function to anint
, then the accepted solutions of this question will look something like: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:
Among the reasons for the better performance is the skipped branching.
If you need to be able to compile code in environments that support the C++11 standard, but also need to be able to compile that same code in environments that don't support it, you could use a function macro to choose between std::round() and a custom function for each system. Just pass
-DCPP11
or/DCPP11
to the C++11-compliant compiler (or use its built-in version macros), and make a header like this:For a quick example, see http://ideone.com/zal709 .
This approximates std::round() in environments that aren't C++11-compliant, including preservation of the sign bit for -0.0. It may cause a slight performance hit, however, and will likely have issues with rounding certain known "problem" floating-point values such as 0.49999999999999994 or similar values.
Alternatively, if you have access to a C++11-compliant compiler, you could just grab std::round() from its
<cmath>
header, and use it to make your own header that defines the function if it's not already defined. Note that this may not be an optimal solution, however, especially if you need to compile for multiple platforms.It might be an inefficient dirty way of conversion but heck, it works lol. And it's good, because it applies to the actual float. Not just affecting the output visually.
There are 2 problems we are looking at:
Rounding conversions mean rounding ± float/double to nearest floor/ceil float/double. May be your problem ends here. But if you are expected to return Int/Long, you need to perform type conversion, and thus "Overflow" problem might hit your solution. SO, do a check for error in your function
from : http://www.cs.tut.fi/~jkorpela/round.html
I did this:
As pointed out in comments and other answers, the ISO C++ standard library did not add
round()
until ISO C++11, when this function was pulled in by reference to the ISO C99 standard math library.For positive operands in [½, ub]
round(x) == floor (x + 0.5)
, where ub is 223 forfloat
when mapped to IEEE-754 (2008)binary32
, and 252 fordouble
when it is mapped to IEEE-754 (2008)binary64
. The numbers 23 and 52 correspond to the number of stored mantissa bits in these two floating-point formats. For positive operands in [+0, ½)round(x) == 0
, and for positive operands in (ub, +∞]round(x) == x
. As the function is symmetric about the x-axis, negative argumentsx
can be handled according toround(-x) == -round(x)
.This leads to the compact code below. It compiles into a reasonable number of machine instructions across various platforms. I observed the most compact code on GPUs, where
my_roundf()
requires about a dozen instructions. Depending on processor architecture and toolchain, this floating-point based approach could be either faster or slower than the integer-based implementation from newlib referenced in a different answer.I tested
my_roundf()
exhaustively against the newlibroundf()
implementation using Intel compiler version 13, with both/fp:strict
and/fp:fast
. I also checked that the newlib version matches theroundf()
in themathimf
library of the Intel compiler. Exhaustive testing is not possible for double-precisionround()
, however the code is structurally identical to the single-precision implementation.