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

134,221

Solution 1

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.

Solution 2

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

Solution 3

#include <math.h>

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

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

Solution 4

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;
}

Solution 5

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.

Share:
134,221

Related videos on Youtube

T.T.T.
Author by

T.T.T.

Updated on July 09, 2022

Comments

  • T.T.T.
    T.T.T. almost 2 years

    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.

  • Jason
    Jason over 15 years
    that round to the nearest integer...not what he asked for.
  • Jason
    Jason over 15 years
    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.
  • Jason
    Jason over 15 years
    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; }
  • T.T.T.
    T.T.T. over 15 years
    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.
  • Eduard - Gabriel Munteanu
    Eduard - Gabriel Munteanu over 15 years
    Tommy, roundf() is defined in C99, so every compliant compiler should support it. Perhaps you're not linking with the math library?
  • T.T.T.
    T.T.T. over 15 years
    It is coming from floating point inaccuracy, I changed to double, works great. Thanks.
  • Jason
    Jason over 15 years
    I don't think the newer visual studio's made any effort to support C99.
  • Jason
    Jason over 15 years
    You could just use this though: floor((10 * x) + 0.5) / 10;
  • Emanuel Ey
    Emanuel Ey about 11 years
    @EvanTeran you are right VS does not support C99 at all -only C89. M$ only seems interested in supporting C++, not C.
  • Spike0xff
    Spike0xff over 10 years
    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.
  • uchuugaka
    uchuugaka about 10 years
    You can use ceilf() and floorf() and roundf() respectively for floats.
  • Timofey Gorshkov
    Timofey Gorshkov over 9 years
    (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
    Timofey Gorshkov over 9 years
    Also it is better to do so: conver>0f ? floor(conver+0.5f) : ceil(conver-0.5f) — to work with negatives as well.
  • chux - Reinstate Monica
    chux - Reinstate Monica over 8 years
    @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
    chux - Reinstate Monica over 8 years
    "A nice trick is to add 0.5," fails in many cases: see comment.