tags:

views:

561

answers:

8

Is there any way to round numbers in C?

I do not want to use ceil and floor. Is there any other alternative?

I came across this code snippet when I Googled for the answer:

(int)(num < 0 ? (num - 0.5) : (num + 0.5))

The above line always prints the value as 4 even when float num =4.9.

Please suggest a solution.

+5  A: 

4.9 + 0.5 is 5.4, which cannot possibly round to 4 unless your compiler is seriously broken.

I just confirmed that the Googled code gives the correct answer for 4.9.

marcelo@macbookpro-1:~$ cat round.c 
#include <stdio.h>

int main() {
    float num = 4.9;
    int n = (int)(num < 0 ? (num - 0.5) : (num + 0.5));
    printf("%d\n", n);
}
marcelo@macbookpro-1:~$ make round && ./round
cc     round.c   -o round
5
marcelo@macbookpro-1:~$
Marcelo Cantos
Hmmm....You're right....The statement can be further simplified to:int n = (num < 0) ? (num - 0.5) : (num + 0.5);I've checked this and it works flawless.Can you please explain how the (num<0) comparison works?I inserted a breakpoint in my IDE and saw that the condition check (num<0) always points to FALSE, which should execute (num + 0.5) always
webgenius
Not sure what you are asking, but an expression `a ? b : c` evaluates to `b` if `a` is true and to `c` otherwise. In this case the idea is to move the value of `num` away from zero by `0.5` before converting it to int by truncating the decimals. This way the truncation will round to the nearest int (e.g. 0.5 + 0.5 = 1.0 and 0.99 + 0.5 = 1.49 both truncate to 1).
Arkku
But why is (num<0) comparison done? num will be always 4.9
webgenius
The comparison is done because the statement is for a general-use-case (where num could be positive or negative), not for the specific case in his example program. If the whole point of the question was, "how do you round 4.9 to 5?" then we could just put `float num = 5.0` and be done with it.
Dan Story
This produces 4 with ./gcc -frip-fabric-of-space-time. There's a plugin for emacs that turns this on by default.
Tim Post
+1  A: 

A general solution is to use rint() and set the FLT_ROUNDS rounding mode as appropriate.

Dan Story
A: 

Try moving the brackets on your solution above, so that it reads:

(int)(num < 0) ? (num - 0.5) : (num + 0.5)

Using num as 4.9 it rounds to 5 on my machine.

Ali Lown
This has no effect other than to possibly raise a warning when you assign this expression to an int. Also, the `(int)` cast is redundant, since `num < 0` already has type `int`.
Marcelo Cantos
What do you mean this is can't possibly work. This is the same as the answer that has 4 up votes.
Ali Lown
I didn't say it can't possible work, I said it has no effect, by which I meant that removing the parentheses as you did doesn't change anything.
Marcelo Cantos
+1  A: 

I think what you're looking for is: int n = (d - floor(d) > 0.5) ? ceil(d) : floor(d);

Shiroko
"I do not want to use ceil and floor" ...
IVlad
If the questioner genuinely doesn't want to use ceil and floor, but genuinely is happy to use the built-in conversion to int, then the question can be filed under "quirky interview-style questions which involve an unnatural restriction to illustrate some point fully understood only by the interviewer". Unfortunately that doesn't fit in a tag.
Steve Jessop
Steve, you are right. This is an question often asked in interviews.
webgenius
A: 

You may be able to use fesetround() in fenv.h (introduced in C99). The possible arguments are the macros FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, and FE_UPWARD but note that not all of them are necessarily defined - only the ones supported by the platform/implementation are. Then you can use the various round, rint and nearbyint functions in math.h (also C99). This way you can set the desired rounding behaviour once and call the same function regardless of whether or not the value is positive or negative.

(With e.g. lround you usually need not even set the rounding direction for normal use to usually get what you want.)

Arkku
A: 

I'm not sure that's such a good idea. That code depends on casts, and I'm fairly sure that the exact truncation is undefined.

float result = (num - floor(num) > 0.5) ? ceil(num) : floor(num);

I'd say that this is a much better way (which is basically what Shiroko posted) since it doesn't depend on any casts.

DeadMG
+1  A: 

the googled code works correctly. The idea behind it is that you round down when the decimal is less than .5 and round up otherwise. (int) casts the float into a int type which just drops the decimal. If you add .5 to a positive num, you get drop to the next int. If you subtract .5 from a negative it does the same thing.

datdo
A: 
int round(double x)
{
return x >= 0.0 ? int(x + 0.5) : int(x - int(x-1) + 0.5) + int(x-1);
}

It will be faster, than a version with ceil and floor.

Ekimov Alexander