38

Duplicate of: round() for float in C++


I'm using VS2008 and I've included math.h but I still can't find a round function. Does it exist?

I'm seeing a bunch of "add 0.5 and cast to int" solutions on google. Is that the best practice?

Community
  • 1
  • 1
Restore the Data Dumps
  • 38,967
  • 12
  • 96
  • 122
  • 1
    add 0.5 and cast to int won't work for negative numbers. The cast truncates (so it rounds -4.5 to -4). So attempting to round -5.0 will give you an output of-4 with this method. Replace the cast with ceil() and it should work. But yes, you have to implement your own, or find it in a 3rd party lib. – jalf Feb 16 '09 at 19:11
  • Er, assume I wrote floor() above, of course. To use ceil, you'd have to subtract 0.5 – jalf Feb 16 '09 at 19:17
  • @jalf as I noted in [my answer to the dup](http://stackoverflow.com/a/24348037/1708801) there are a lot of issues with rolling your own and today even if you are stuck with *C++03* boost would be a better recommendation than attempting to roll your own. – Shafik Yaghmour Jul 14 '14 at 12:05

4 Answers4

62

You may use C++11's std::round().

If you are still stuck with older standards, you may use std::floor(), which always rounds to the lower number, and std::ceil(), which always rounds to the higher number.

To get the normal rounding behaviour, you would indeed use floor(i + 0.5).

This way will give you problems with negative numbers, a workaround for that problem is by using ceil() for negative numbers:

double round(double number)
{
    return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
}

Another, cleaner, but more resource-intensive, way is to make use of a stringstream and the input-/output-manipulators:

#include <iostream>
#include <sstream>

double round(double val, int precision)
{
    std::stringstream s;
    s << std::setprecision(precision) << std::setiosflags(std::ios_base::fixed) << val;
    s >> val;
    return val;
}

Only use the second approach if you are not low on resources and/or need to have control over the precision.

Patrick Glandien
  • 7,791
  • 5
  • 41
  • 47
  • 43
    You think it's *cleaner* to convert to a string and back? – Paul Tomblin Feb 16 '09 at 19:12
  • Yes, using the +0.5-technique you will encounter problems with negative numbers and you also don't have control over the precision. – Patrick Glandien Feb 16 '09 at 19:14
  • 1
    +0.5 should work fine as long as you use floor(). Anyway, then it becomes a question of correctness, and not which is cleaner. – jalf Feb 16 '09 at 19:16
  • what problems are there with negative numbers? if you don't need control precision then the stringstream solution is way slower for no reason. maybe a template-specialization would make sense here, if you really want to give precision control. – wilhelmtell Feb 16 '09 at 19:19
  • also, i should remind you that 0.5 is represented as an exact number. – wilhelmtell Feb 16 '09 at 19:20
  • 3
    Needed also to include (using MSVC 2012) to use the round function. – Vertexwahn May 07 '13 at 14:35
  • 1
    I prefer `copysignf(floorf(fabs(x) + 0.5f), x)` as it's branchless and the code that simulates the branch is literally bin-ops (`abs` -> `&~0x80000000`, copysign is a bit transfer, etc) – LiraNuna Mar 23 '14 at 21:10
  • See my answer [here](http://stackoverflow.com/a/24348037/1708801), there is also `trunc` and `boost` available. Also see my link's to Pascal Cuoq's articles on why rolling your own can be very tricky. – Shafik Yaghmour Jun 27 '14 at 01:43
  • @wilhelmtell "what problems are there with negative numbers?" --> in the corner case of `round(-0.0)`, this answer returns `0.0`. `-0.0` may be expected. – chux - Reinstate Monica Aug 03 '15 at 19:18
  • Question starts with "I'm using VS2008..." and the answer starts with "You may use C++11's..." Don't you think there is some contradiction here? There is no std::round() function in VC2008. – il--ya Apr 12 '18 at 14:44
  • Note that the +0.5 trick is not completely right: http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1 – ChriS May 23 '18 at 10:11
14

Using floor(num + 0.5) won't work for negative numbers. In that case you need to use ceil(num - 0.5).

double roundToNearest(double num) {
    return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5);
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
3

There actually isn't a round function in Microsoft math.h.
However you could use the static method Math::Round() instead.
(Depending on your project type.)

Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
  • Visual studio now supports round [see my comment here](http://stackoverflow.com/questions/485525/round-for-float-in-c#comment37681329_485525) also see my [answer](http://stackoverflow.com/a/24348037/1708801) for what I think is a full set of alternatives in a case where you can not use a more modern compiler. – Shafik Yaghmour Jul 01 '14 at 13:22
0

I don't know if it's best practice or not but using the 0.5 technique with a floor() seems to be the way to go.

Elroy
  • 605
  • 4
  • 12
  • 20