473,890 Members | 1,178 Online

# Floor and ceil function

16 New Member
I've learned that we can round up and down a float number by using Ceil and floor function. But, is this function still able to work if I the number I want to round up (or down) is zero?
I have wrote my codes, but somehow it didn't give the right answer if the number is zero. My simple code looks like this:

Expand|Select|Wrap|Line Numbers
1. #include <math.h>
2. int main(){
3.
4. printf("The nearest integer from %f is %f\n", 0,ceil(0) );
5. }
6.
The resut is like this:
"The nearest integer from 0.000 is 1.000"

And the same answer happen if I change Ceil to floor.
Did I miss something?

May 26 '09 #1
7 25763
JosAH
11,448 Recognized Expert MVP
What compiler are you using? I get 0.000000 for an answer and I used a couple of compilers.

kind regards,

Jos
May 26 '09 #2
unauthorized
81 New Member
You can always write your own macro if your compiler is screwing up:

Expand|Select|Wrap|Line Numbers
1. #define CEIL(VARIABLE) ( (VARIABLE - (int)VARIABLE)==0 ? (int)VARIABLE : (int)VARIABLE+1 )
Any questions?

Or if you hate macros as much as any CSc professor, you can do this:

Expand|Select|Wrap|Line Numbers
1. int CEIL(double var)
2. {
3.      int integer = (int)var;
4.      if(var - integer == 0) return integer;
5.      else return integer + 1;
6. }
May 26 '09 #3
mingke
16 New Member
I have tried another way. I declared an array (arr[5]) and use ceil and floor function. If the number is not zero, the result came out fine, but if the number is zero the result came out not fine. Because sometime it right but for another array,it results 1.000
My code looks like this;
Expand|Select|Wrap|Line Numbers
1. # include <math.h>
2. int main(){
3. float arr[5],c[5];
4. int i;
5.
6. arr[0]=-2.828427; arr[1]=-0.707107; arr[2]=0.000000;arr[3]=-0.707107;
7. arr[4]=0.000000;
8.
9. for (i=0;i<5;i++){
10.   c[i]=ceil (arr[i]);
11.   printf ("%f\n",c[i]);
12. }
13.
14. }
15.
And the result is like this:
-2.000000
0.000000
1.000000
0.000000
0.000000

Is it my compiler problem?If it is, what do you think that make it screw up?
Oh yeah, I use Dev C++ as my compiler.

Thank you
May 26 '09 #4
donbock
2,426 Recognized Expert Top Contributor
@unauthorized
The C Standard says that ceil(x) "returns the smallest integral value not less than x, expressed as a double."

Neither of your examples returns a double.
Both of your examples depend on how the compiler behaves when you cast a double to an integer (round, truncate, other). That's implementation-defined behavior; not something you can count on. For example, C99 allows you to select between four different rounding modes.
May 26 '09 #5
donbock
2,426 Recognized Expert Top Contributor
@mingke
I don't know why it would make a big difference, but the input and return value for ceil are both doubles. Try changing line 3 to declare arrays of double rather than arrays of float. No change needed on line 11 after you change line 3 because %f converts a double value (you, however, were passing a float value).
May 26 '09 #6
unauthorized
81 New Member
@donbock
My examples were not meant to be 1 to 1 clone of the standard library. Heck, they weren't even very safe (cast double->int can cause an overflow). I don't see why you are making a point of this.

I admit that my examples were based on my previous experiences when casting. However, the C99 standard states:
When a finite value of real floating type is converted to an integer type other than _Bool,
the fractional part is discarded (i.e., the value is truncated toward zero). If the value of
the integral part cannot be represented by the integer type, the behavior is undefined.
Would you elaborate on the "4 different ways" you wrote of?

edit:
I tried compiling your code in the latest version of Dev-C++ and it works fine. My output was -2, 0, 0, 0, 0.
May 26 '09 #7
donbock
2,426 Recognized Expert Top Contributor
@unauthorized
I was unaware of this. Thanks for bringing it to my attention. You're right -- this knocks out my objection regarding implementation-defined behavior.
@unauthorized
C99 added fenv.h. That header makes functions fegetround and fesetround available. These functions get and set the rounding mode. Possible rounding modes are FE_DOWNWARD (similar to floor function), FE_TONEAREST, FE_TOWARDZERO (similar to casting floating type to integral type), and FE_UPWARD (similar to ceil function). I only brought this up because I thought implementation-defined behavior from casting a double to int might be in accordance with the current rounding mode. We now know that is not the case.
May 26 '09 #8