Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::nearbyint vs std::round in C++11

C++11 introduced the std::nearbyint and std::round functions. Both return the "nearest" integer value.

When and where should I prefer one over the other?

I have tested them with the value of 0.5:

Case 1 : Demo for nearbyint

#include <iostream>
#include <cmath>

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

output: 0

Case 2 : Demo for round

#include <iostream>
#include <cmath>

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

output: 1

Why are the outputs different?

like image 362
msc Avatar asked Nov 07 '17 11:11

msc


People also ask

What is STD round?

The std::round function returns a floating point value, "rounding halfway cases away from zero".

How do I always round up in C++?

The round() function is used to round the values that have the data type of float, double, and long double. We simply pass these values to the parameters of this round() function, and this function rounds these values to the nearest integer value.

How do you round doubles in C++?

round() in C++. The round() function in C++ is used to round off the double, float or long double value passed to it as a parameter to the nearest integral value. The header file used to use the round() function in a c++ program is <cmath> or <tgmath>.

How do you round to the nearest hundredth in C++?

To round to nearest hundredth: Ex: moneyValue = floor(floatValue*100+0.5)/100; If moneyValue was stored as 8.12345, it is now stored as 8.12.


2 Answers

The std::round function ignores the current rounding mode while the std::nearbyint takes it into account. You can change the rounding mode:

#include <cfenv>
int main() {
    std::fesetround(FE_UPWARD);
    // perform calculations
    std::fesetround(FE_DOWNWARD);
    // perform calculations
    // other rounding methods...
}

and observe different results. To obtain the current rounding mode value use the std::fegetround() function. Chances are the default (implementation defined) value is 0 which translates to FE_TONEAREST.

like image 139
Ron Avatar answered Oct 05 '22 11:10

Ron


As pointed out in Ron's answer, one difference between rint() and nearbyint() on one hand, and round() on the other hand, is that the latter uses a fixed rounding mode, regardless of the dynamic rounding mode currently in effect. The details of this cannot be found in the 2011 ISO C++ standard, which in section 26.8 C library [c.math] simply points to the C standard. The 1999 ISO C standard specifies the operation of round() as follows:

7.12.9.6 [...] The round functions round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction.

The specific rounding mode used by round() is listed in section 4.3.1 of the IEEE 754 (2008) floating-point standard as roundTiesToAway, meaning tie cases are rounded away from zero. But the usual binding of FE_TONEAREST is to the IEEE-754 (2008) rounding mode roundTiesToEven, meaning such tie cases round to an even integer. In fact, that is the only implementation of FE_TONEAREST I have ever encountered on any of numerous system platforms I have used that support fesetround().

The difference in the handling of these two variants of rounding "to nearest" is apparent in the asker's example: 0.5 rounds to the next larger (in magnitude) integer (1) when using round(), but it rounds to an even integer (0) when nearbyint() or rint() are used.

like image 44
njuffa Avatar answered Oct 05 '22 12:10

njuffa