29

Is there a function to round a float in C or do I need to write my own?

float conver = 45.592346543;

I would like to round the actual value to one decimal place, conver = 45.6.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
T.T.T.
  • 33,367
  • 47
  • 130
  • 168

7 Answers7

33

As Rob mentioned, you probably just want to print the float to 1 decimal place. In this case, you can do something like the following:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);
  return 0;
}

If you want to actually round the stored value, that's a little more complicated. For one, your one-decimal-place representation will rarely have an exact analog in floating-point. If you just want to get as close as possible, something like this might do the trick:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);

  conver = conver*10.0f;
  conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
  conver = conver/10.0f;

  //If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
  //conver = roundf(conver*10.0f)/10.0f;

  printf("conver is now %f\n",conver);
  return 0;
}

I doubt this second example is what you're looking for, but I included it for completeness. If you do require representing your numbers in this way internally, and not just on output, consider using a fixed-point representation instead.

Matt J
  • 43,589
  • 7
  • 49
  • 57
  • Rounds down seems to work OK but for example rounding 45.569346543; is 45.599998....or 45.5 with *1.0f....I'm closer thought, need to read floor and ceil again. thanks guys. – T.T.T. Jan 30 '09 at 21:04
  • It is coming from floating point inaccuracy, I changed to double, works great. Thanks. – T.T.T. Jan 30 '09 at 22:46
  • Just to reiterate Matt J's closing comment which I'm not sure you absorbed: 45.6 cannot be represented exactly in ANY binary floating point format, so that isn't what's being stored, even when you use double. If your program is now printing "45.6" it's because the output routines are rounding it for you. – Spike0xff Dec 23 '13 at 18:20
  • `(conver >= (floor(conver)+0.5f)) ? ceil(conver) : floor(conver)` is equivalent to `floor(conver+0.5f)` (i think, you've meant exactly `>=`, not `>`). – Timofey Gorshkov Nov 21 '14 at 12:13
  • 1
    Also it is better to do so: `conver>0f ? floor(conver+0.5f) : ceil(conver-0.5f)` — to work with negatives as well. – Timofey Gorshkov Nov 21 '14 at 12:18
32

Sure, you can use roundf(). If you want to round to one decimal, then you could do something like: roundf(10 * x) / 10

  • 1
    Nice, everyone else ignored the fact that the asker didn't ask to round to nearest integer. It should be noted that because of imprecision in floating point. When printing you will likely see "45.59999" given the example. – Evan Teran Jan 30 '09 at 20:13
  • A nice more general solution would be: double f(double x, int decimal_points) { int n = pow(10, decimal_points); return roundf(n * x) / n; } – Evan Teran Jan 30 '09 at 20:15
  • unresolved external symbol _roundf referenced in function _f have included math.h but it doesn't like roundf() I am in VS .NET, is foundf only for linux? – T.T.T. Jan 30 '09 at 20:45
  • Tommy, roundf() is defined in C99, so every compliant compiler should support it. Perhaps you're not linking with the math library? – Eduard - Gabriel Munteanu Jan 30 '09 at 21:09
  • 1
    I don't think the newer visual studio's made any effort to support C99. – Evan Teran Jan 31 '09 at 03:31
  • You could just use this though: floor((10 * x) + 0.5) / 10; – Evan Teran Jan 31 '09 at 03:32
  • @EvanTeran you are right VS does not support C99 at all -only C89. M$ only seems interested in supporting C++, not C. – Emanuel Ey Feb 11 '13 at 16:57
  • @EvanTeran `floor((10 * x) + 0.5) / 10;` fails for negatives number and for positive numbers where the sum of `(10 * x) + 0.5` itself rounds up before the `floor()` is called. – chux - Reinstate Monica Jan 29 '16 at 14:37
2
#include <math.h>

double round(double x);
float roundf(float x);

Don't forget to link with -lm. See also ceil(), floor() and trunc().

Nathan Campos
  • 28,769
  • 59
  • 194
  • 300
Joao da Silva
  • 7,353
  • 2
  • 28
  • 24
1

To print a rounded value, @Matt J well answers the question.

float x = 45.592346543;
printf("%0.1f\n", x);  // 45.6

As most floating point (FP) is binary based, exact rounding to one decimal place is not possible when the mathematically correct answer is x.1, x.2, ....

To convert the FP number to the nearest 0.1 is another matter.

Overflow: Approaches that first scale by 10 (or 100, 1000, etc) may overflow for large x.

float round_tenth1(float x) {
  x = x * 10.0f;
  ...
}

Double rounding: Adding 0.5f and then using floorf(x*10.0f + 0.5f)/10.0 returns the wrong result when the intermediate sum x*10.0f + 0.5f rounds up to a new integer.

// Fails to round 838860.4375 correctly, comes up with 838860.5 
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
  if (x < 0.0) {
    return ceilf(x*10.0f + 0.5f)/10.0f;
  }
  return floorf(x*10.0f + 0.5f)/10.0f;
}

Casting to int has the obvious problem when float x is much greater than INT_MAX.


Using roundf() and family, available in <math.h> is the best approach.

float round_tenthA(float x) {
  double x10 = 10.0 * x;
  return (float) (round(x10)/10.0);
}

To avoid using double, simply test if the number needs rounding.

float round_tenthB(float x) {
  const float limit = 1.0/FLT_EPSILON;
  if (fabsf(x) < limit) {
    return roundf(x*10.0f)/10.0f;
  }
  return x;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

Just to generalize Rob's answer a little, if you're not doing it on output, you can still use the same interface with sprintf().

I think there is another way to do it, though. You can try ceil() and floor() to round up and down. A nice trick is to add 0.5, so anything over 0.5 rounds up but anything under it rounds down. ceil() and floor() only work on doubles though.

EDIT: Also, for floats, you can use truncf() to truncate floats. The same +0.5 trick should work to do accurate rounding.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • You can use `ceilf()` and `floorf()` and `roundf()` respectively for floats. – uchuugaka Feb 05 '14 at 01:46
  • "A nice trick is to add 0.5," fails in many cases: [see comment](http://stackoverflow.com/questions/497018/is-there-a-function-to-round-a-float-in-c-or-do-i-need-to-write-my-own#comment57895810_497037). – chux - Reinstate Monica Jan 29 '16 at 14:39
0

you can use #define round(a) (int) (a+0.5) as macro so whenever you write round(1.6) it returns 2 and whenever you write round(1.3) it return 1.

redblood
  • 542
  • 1
  • 4
  • 19
-1

There is a round() function, also fround(), which will round to the nearest integer expressed as a double. But that is not what you want.

I had the same problem and wrote this:

#include <math.h>

   double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures.  Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/

{
    double     a, b;
    long long  i;
    int        neg = 0;


    if(!value) return value;

    if(value < 0.0)
    {
        value = -value;
        neg = 1;
    }

    i = nsig - log10(value);

    if(i) a = pow(10.0, (double)i);
    else  a = 1.0;

    b = value * a;
    i = b + 0.5;
    value = i / a;

    return neg ? -value : value;
} 
Garrett Hyde
  • 5,409
  • 8
  • 49
  • 55