0

I was asking about round a number half up earlier today and got great help from @alk. In that post, my thinking was to round up 4.5 to 5 but round 4.4 down to 4. And the solution given by @alk was:

int round_number(float x)
{
 return x + 0.5;
}

and it works very elegantly!

In this post, I would like to discuss how to implement the ceil() function in C. Along the same line as the last solution given by @alk, I came up with the following:

int round_up(float y)
{
   return y + 0.99999999;
}

This works for all situations except when the the float number y has .00000001. I am wondering if there's any better way to do the same thing as ceil() in C.

phuclv
  • 37,963
  • 15
  • 156
  • 475
TonyW
  • 18,375
  • 42
  • 110
  • 183
  • You question asked how to **round up** then in the content you said **ceil()** function. That's completely different. You should edit it – phuclv Mar 02 '14 at 07:16
  • I don't think there's a way to do this reliably without getting in bed with the floating point format. – Hot Licks Mar 03 '14 at 00:03

3 Answers3

2

Unless you reliably know the epsilon of float (I'm not sure standard C provides that), I think you're stuck with return (y < 0 || y == (int)y) ? y : y + 1;

Mike Woolf
  • 1,210
  • 7
  • 11
1

This fails for negative numbers.

int round_up(float y) {
 return y + 0.99999999;
}

But let's use that to our advantage. float to int conversion is a truncate toward 0.0. Thus negative numbers are doing a "round up" or "ceiling" function. When we have a positive float, convert to int noting this is a "floor" function. Adjust when y is not an integer.

(Assume y within INT_MIN ... INT_MAX.)

int ceil(float y) {
   if (y < 0) {
     return y;  // this does a ceiling function as y < 0.
   }
   int i = y; // this does a floor function as y >= 0.
   if (i != y) i++;
   return i;
 }

void ceil_test(float y) {
   printf("%f %d\n", y, ceil(y));
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

The first snippet works incorrectly for negative numbers. -3.5 will be come -3, not -4. To round values properly use

int round_number(float x)
{
    if (x >= 0)
        return x + 0.5f;
    else
        return x - 0.5f
}

Even that way it's still incorrect for 2 values. See Why does Math.round(0.49999999999999994) return 1?. Note that you need to use the f suffix to get the float literal, otherwise the operation will be done in double precision and then downcast back to float

For ceiling, adding 1 is enough

int ceiling(float x)
{
    if (x < 0 || (int)x == x)
        return x;
    else
        return x + 1.0f;
}

When x is an integer, e.g. x = 3.0 (or -3.0), it returns 3 (or -3). For x = 3.1 it returns 4, for x = -3.1 it returns -3

phuclv
  • 37,963
  • 15
  • 156
  • 475