views:

384

answers:

3

Hi i want to round double numbers like this (away from zero) in C++:

  4.2 ---->   5
  5.7 ---->   6
 -7.8 ---->  -8
-34.2 ----> -35

What is the efficient way to do this?

A: 

try

 double rounded = _copysign(ceil(abs(x)), x);
Frank Bollack
Doesnt work for the negative ones
Ruben Bartelink
but ceil returns bigger integer value if my value is -3.4 and i add 0.5 it will be -2.9 and ceil will return -2 i want something to make -4
Emre
ceil(x + 0.5) for x=5.7 would yield 7 instead of 6, wouldn't it?
samuil
It still doesnt work for the negative ones as specced, see the samples at the place I linked
Ruben Bartelink
changed the answer after reading the question again more carefully...
Frank Bollack
Now it's not as efficient anymore, even if it uses an interesting trick - where is _copysign from?
Ruben Bartelink
+17  A: 
inline double myround(double x)
{
  return x < 0 ? floor(x) : ceil(x);
}

As mentioned in the article Huppie cites, this is best expressed as a template that works across all float types

See http://www.cplusplus.com/reference/clibrary/cmath/floor/ and http://www.cplusplus.com/reference/clibrary/cmath/ceil/

or, thanks to Pax, a non-function version:

x = (x < 0) ? floor(x) : ceil(x);
Ruben Bartelink
thank you it works
Emre
Good call, @Ruben, added a non-function variant and gave you a vote. Hope you don't mind (the edit, that is, obviously you don't mind the vote).
paxdiablo
Waiting for 3k myself - added in an inline specifier - I'd tend to try to find a good name and stick it in a util lib, probably as a template for all floats -- it wouldnt cost any efficiency and allows you to quickly isolate or change all usages of it
Ruben Bartelink
+1  A: 

There is a nice article about a similar problem on CPlusPlus.com. The easy solution to your problem should be something like this:

double customRound( double value ) const {
   return value < 0 ? floor( value ) : ceil( value );
}

A better solution is the one mentioned in the article, which uses a template:

//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
   FloatType result = std::ceil( std::fabs( value ) );
   return (value < 0.0) ? -result : result;
}
Huppie
Why isnt it called customFloor - it's neither :P
Ruben Bartelink
I see in the cited article its impl'd as <code>template <typename FloatType> FloatType ceil0( const FloatType return (value < 0.0) ? -result : result; }</code>Interesting article, +1
Ruben Bartelink
@Ruben Bartelink: 'Round' should be better :)... btw... you have some ninja typing skills ;-)
Huppie
Typing or cut and pasting :P My typing is actually quite embarassing - see http://blog.jpboodhoo.com/TypersharkNdashImproveYouTypingInJustMinutesADay.aspx (No, havent done it yet). I think even 'Round' is a bit generic and has a generally understood meaning in the stdlib - point is its a very specific algorithm he wants, and using either floor, ceil or round doesnt accurately convey that.
Ruben Bartelink