views:

146

answers:

2

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

In cmath there is floor and ceiling, but I cannot find round. How does one round with the standard library without writing a function and dragging it around into all projects?

Thanks

A: 

std::floor(x + 0.5) or std::ceil(x - 0.5), depending on how you want to handle the half-integer case.

They are overloaded functions, so if you want to wrap them, you do:

template <typename T>
T round(T x) 
{
    return std::floor((T)0.5 + x);
}

Don't listen to what people say in the commentaries, floor(-1.6 + 0.5) = floor(-1.1) = -2 as expected.

Alexandre C.
@ring0: right, I spoke to fast...
Alexandre C.
@ring0 maybe, there is more than one way to round
jk
@ring0: Still not awake... There was no problem in the first place.
Alexandre C.
Hmm what about when `x = -1.5`? Expected result `-2`, but `floor(-1.0)` is `-1` ... :-)
ring0
@ring0: That's why I gave the choice between floor(x+.5) and ceil(x-.5). There are different choices for half integers. There you can discriminate between negative and positive numbers. IMO, this not big a concern.
Alexandre C.
+4  A: 

If you are in C++ you need to write you own round()

template < typename T > T round(const T &x) { return static_cast<int>(x+0.5-(x<0)); }

The same goes for C89. C99 already includes round function in math.h

Edit: as catched by Alexander, floor returns -2 for -1.x, sorry for the mistake (its not as flexible as it was now)

Let_Me_Be
I'd upvote this, if you didn't use a macro... an inline function for C++ would be better.
Matteo Italia
@Matteo Give me one reason why an inline function would be better. And I don't mean in general, I mean in this exact example.
Let_Me_Be
same for the macro/inline (as Matteo Italia) ! But +1 because it's better to keep using cmath (better integration in c++, functions are living in std etc...) and recreate round from floor. Including the former lib math.h just for one function seems weird to me...
Elenaher
@Let_Me_Be: Type safety? Scoping? (notice that I'm not the one who downvoted it, actually I was going to upvote it)
Matteo Italia
if x is an expression involving an operator with precedence less than + you may get odd results
jk
@jk: I don't think so, `x` is enclosed in parens.
Matteo Italia
With the current edit, there's also a double evaluation of `x`. Now it should *definitely* be an inline function.
Matteo Italia
so it does, i'd still go with the inline function for the other stated reasons
jk
@Let_Me_Be: Well done, you got my +1 :)
Matteo Italia
Aren't you assuming a Boolean evaluating to True is necessary equal to 1, when casted to an integer ? This is undefined behaviour indeed.
wok
@wok That should be defined in standard for both C and C++ (at least for C it definitely is).
Let_Me_Be
@wok : No. C++ standards assures that (int)True == 1 (I've just checked it in Bjarne Stroustrup's book : "The C++ language")
Elenaher
@wok: Nope. See §4.5.4 of the standard: "An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one."
Matteo Italia
Alright, I was wrong.
wok
The negative case doens't work.
Alexandre C.
@Alexandre Hmm, on what value exactly? `-0.3->0`, `-0.5->-1`, `-0.9->-1`. Seems to work fine here.
Let_Me_Be
@Let_Me_Be: -0.3->-1, -0.5->-1, -0.9->-2. Don't forget that floor(-1.3) is -2, not -1.
Alexandre C.
More simply, -1 ! (gives `-2` instead of `-1`)
ring0
@Alexandre LOL, my compiler deceived me :-D Thx for the catch.
Let_Me_Be