views:

17532

answers:

9

I need a simple floating point rounding function, thus:

double round(double);

round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1

I can find ceil() and floor() in the math.h - but not round().

Is it present in the standard C++ library under another name, or is it missing??

+17  A: 

It's usually implemented as floor(value + 0.5).

Edit: and it's probably not called round since there are at least three rounding algorithms I know of: round to zero, round to closest integer, and banker's rounding. You are asking for round to closest integer.

MSN

MSN
Um, that's why you add 0.5.
MSN
It's good to make the distinction between different versions of 'round'. It's good to know when to pick which, too.
xtofl
+14  A: 

There's no round() in the C++ std library. You can write one yourself though:

double round(double d)
{
  return floor(d + 0.5);
}

The probable reason there's no round in the C++ std library is that it can in fact be implemented in different ways. The above is one common way, but there are others as round-to-even which is less biased and generally better if you're going to do a lot of rounding. It's a bit more complex to implement, though.

Andreas Magnusson
This doesn't handle negative numbers correctly. The answer by litb is correct.
Registered User
@InnerJoin: Yes, it handles negative numbers differently to litb's answer, but that doesn't make it "incorrect".
Roddy
@Andreas Magnusson: What if you want to round to some places after the decimal precision? multiply and divide?
Lazer
@Lazer: I would be careful to mul-div floating-point values. There's no guarantee that (f * 10) / 10 == f for a floating-point value. That said, a mul-div is probably the easiest way to achieve it...
Andreas Magnusson
+31  A: 

There is a round function for C99, which will be available in the next C++ too. You can however create such a function manually quite easy:

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

Edit 1: As xtofl notes, this can be called a symmetrical round.

Edit 2: You can also use floor(n + 0.5). It will round halfway numbers such as -0.5 up to 0.0. The function above will round them down to -1.0 . That's how the C99 round function works (rounding halfway numbers always away from zero). I don't know what makes more sense though, but i think it depends on the use of the function.

Johannes Schaub - litb
Nice to notice: this is a symmetrical round.
xtofl
(-0.1) + 0.5 == 0.4. floor(0.4) == 0.0. (-0.1) + (-0.5) == -0.6. floor(-0.6) == -1.0.
Andreas Magnusson
floor(n + 0.5) WILL work for negative numbers, but (int)(n+0.5) doesn't. The floor() approach /is/ correct, AFAICT.
Roddy
roddy, can you please elaborate? floor will return the greatest integer not greater than its argument. it's not what the OP asked for.
Johannes Schaub - litb
fixed it to use ceil and floor depending on the sign. could have come to this solution well earlier though. now i'm really ashamed not seeing that simple floor thingy tho :) let's have a coffee for that hehe
Johannes Schaub - litb
A: 

what i did was

#include <cmath.h>
using namespace std;


    double roundh(double number,int place){
/*place = decimal point. putting in 0 will make it round to whole number. putting in 1 will round to the tenths digit.*/

    number *= 10^place;
    int istack = (int)floor(number);
    int out = number-istack;
if (out < 0.5){
floor(number);
number /= 10^place;
return number;
}
if (out > 0.4) {
ceil(number);
number /= 10^place;
return number;
}
}
A: 

rint function from cmath ?

clement
No. rint is either equivalent to ceil or floor depending on the current rounding mode, which is implementation defined. http://www.opengroup.org/onlinepubs/000095399/functions/rint.html
carleeto
+1  A: 

You could round to n digits precision with:

double round( double x )
{
const double sd = 1000; //for accuracy to 3 decimal places
return int(x*sd + (x<0? -0.5 : 0.5))/sd;
}
carleeto
+4  A: 

There are 2 problems we are looking at:

  1. rounding conversions
  2. type conversion.

Rounding conversions mean rounding ± float/double to nearest floor/ceil float/double. May be your problem ends here. But if you are expected to return Int/Long, you need to perform type conversion, and thus "Overflow" problem might hit your solution. SO, do a check for error in your function

long round(double x) {
   assert(x >= LONG_MIN-0.5);
   assert(x <= LONG_MAX+0.5);
   if (x >= 0)
      return (long) (x+0.5);
   return (long) (x-0.5);
}

#define round(x) ((x) < LONG_MIN-0.5 || (x) > LONG_MAX+0.5 ?\
      error() : ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

from : http://www.cs.tut.fi/~jkorpela/round.html

Sangeet
A nice reference page :)
tersyon
A: 
//convert the float to a string
//might use stringstream but it looks like it truncates the float to only
//5 decimal points (maybe thats what u want anyway =P)

float MyFloat = 5.11133333311111333;
float NewConvertedFloat = 0.0;
string FirstString = " ";
string SecondString = " ";
stringstream ss (stringstream::in | stringstream::out);
ss << MyFloat;
FirstString = ss.str();

//take out how ever many decimal places you want
//(this is a string it includes the point)
SecondString = FirstString.substr(0,5);
//whatever precision decimal place you want

//convert it back to a float
stringstream(SecondString) >> NewConvertedFloat;
cout << NewConvertedFloat;
system("pause");

It might be an inefficent dirty way of conversion but heck, it works lol. And its good because it applies to the actual float. Not just affecting the output visually.

Brad
+2  A: 

A certain type of rounding is also implemented in Boost:

#include <iostream>

#include <boost/numeric/conversion/converter.hpp>

template<typename T, typename S> T round2(const S& x) {
  typedef boost::numeric::conversion_traits<T, S> Traits;
  typedef boost::numeric::def_overflow_handler OverflowHandler;
  typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
  typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
  return Converter::convert(x);
}

int main() {
  std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}

Note that this works only if you do a to-integer conversion.

Philipp