Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do lots of (old) programs use floor(0.5 + input) instead of round(input)?

The differences reside in the returned value giving inputs around tie-breaking I believe, such as this code:

int main() {     std::cout.precision(100);      double input = std::nextafter(0.05, 0.0) / 0.1;     double x1 = floor(0.5 + input);     double x2 = round(input);      std::cout << x1 << std::endl;     std::cout << x2 << std::endl; } 

which outputs:

1 0 

But they are just different results in the end, one chooses its preferred one. I see lots of "old" C/C++ programs using floor(0.5 + input) instead of round(input).

Is there any historic reason? Cheapest on the CPU?

like image 677
markzzz Avatar asked Nov 15 '17 08:11

markzzz


2 Answers

std::round is introduced in C++11. Before that, only std::floor was available so programmers were using it.

like image 148
haccks Avatar answered Sep 18 '22 06:09

haccks


There is no historic reason whatsoever. This kind of deviance has been around since year dot. It's an abuse of floating point arithmetic, and many experienced professional programmers fall for it. Even the Java bods did up to version 1.7. Funny guys.

My conjecture is that a decent out-of-the-box rounding function was not formally available until C++11 (despite C getting theirs in C99), but that really is no excuse for adopting the so-called alternative.

Here's the thing: floor(0.5 + input) does not always recover the same result as the corresponding std::round call!

The reason is quite subtle: the cutoff point for rounding, a.5 for an integer a is a dyadic rational. As this can be represented exactly in an IEEE754 floating point up to the 52nd power of 2, and thereafter rounding is a no-op anyway, std::round always works properly. For other floating point schemes, consult the documentation.

But adding 0.5 to a double can introduce imprecision causing a slight under or overshoot for some values. If you think about it, adding two double values together - that are the inception of unwitting denary conversions - and applying a function that is a very strong function of the input (such as a rounding function), is bound to end in tears.

Don't do it.

Reference: Why does Math.round(0.49999999999999994) return 1?

like image 33
Bathsheba Avatar answered Sep 21 '22 06:09

Bathsheba