Floor and ceil function

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • mingke
    New Member
    • Dec 2008
    • 16

    Floor and ceil function

    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:

    Code:
    #include <math.h> 
    int main(){
    
    printf("The nearest integer from %f is %f\n", 0,ceil(0) );  
    }
    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?

    Thank you for your time.
  • JosAH
    Recognized Expert MVP
    • Mar 2007
    • 11453

    #2
    What compiler are you using? I get 0.000000 for an answer and I used a couple of compilers.

    kind regards,

    Jos

    Comment

    • unauthorized
      New Member
      • May 2009
      • 81

      #3
      You can always write your own macro if your compiler is screwing up:

      Code:
      #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:

      Code:
      int CEIL(double var)
      {
           int integer = (int)var;
           if(var - integer == 0) return integer;
           else return integer + 1;
      }

      Comment

      • mingke
        New Member
        • Dec 2008
        • 16

        #4
        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;
        Code:
        # include <math.h> 
        int main(){
        float arr[5],c[5];
        int i;
        
        arr[0]=-2.828427; arr[1]=-0.707107; arr[2]=0.000000;arr[3]=-0.707107;
        arr[4]=0.000000;
        
        for (i=0;i<5;i++){
          c[i]=ceil (arr[i]);
          printf ("%f\n",c[i]);
        }
        
        }
        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

        Comment

        • donbock
          Recognized Expert Top Contributor
          • Mar 2008
          • 2427

          #5
          Originally posted by unauthorized
          You can always write your own macro if your compiler is screwing up:
          Code:
          #define CEIL(VARIABLE) ( (VARIABLE - (int)VARIABLE)==0 ? (int)VARIABLE : (int)VARIABLE+1 )
          Or if you hate macros as much as any CSc professor, you can do this:
          Code:
          int CEIL(double var)
          {
               int integer = (int)var;
               if(var - integer == 0) return integer;
               else return integer + 1;
          }
          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.

          Comment

          • donbock
            Recognized Expert Top Contributor
            • Mar 2008
            • 2427

            #6
            Originally posted by mingke
            Code:
            # include <math.h> 
            int main(){
            float arr[5],c[5];
            int i;
            
            arr[0]=-2.828427; arr[1]=-0.707107; arr[2]=0.000000;arr[3]=-0.707107;
            arr[4]=0.000000;
            
            for (i=0;i<5;i++){
              c[i]=ceil (arr[i]);
              printf ("%f\n",c[i]);
            }
            }
            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).

            Comment

            • unauthorized
              New Member
              • May 2009
              • 81

              #7
              Originally posted by donbock
              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.
              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.
              Perhaps you should download the latest version of your IDE? A clean installation would be great.

              Comment

              • donbock
                Recognized Expert Top Contributor
                • Mar 2008
                • 2427

                #8
                Originally posted by unauthorized
                I admit that my examples were based on my previous experiences when casting. However, the C99 standard states:
                Originally posted by C99
                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.
                I was unaware of this. Thanks for bringing it to my attention. You're right -- this knocks out my objection regarding implementation-defined behavior.
                Originally posted by unauthorized
                Would you elaborate on the "4 different ways" [rounding modes] you wrote of?
                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.

                Comment

                Working...