Thread: Rounding in C

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    19

    Rounding in C

    What is the best method for traditionally rounding (0.5 up and 0.4 down) in C? I have heard adding 0.5 and called floor or subtracting 0.5 and calling ceil but I want this to be conditional where if my user input value is not a whole number then this is function is called.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    C99 has a function called round() that you can get if you #include <math.h>. Otherwise floor(x+0.5) will also work (note: the ceil technique will round 4.5 -> 4, but it will work for every number strictly greater than a half-integer). You just have to pick one, it doesn't matter. (Note, though, that like most of the math.h functions, round and ceil will both return double rather than int.)

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    19
    So if I specify a variable as an integer and only want to work with whole numbers, what happens if the user inputs 99.7 ?

    If nothing happens it would be safe to say I could round(var); to achieve my desired results?

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Truncation.

    int d = 99.7 results in 99.

    However, you could write a round function easily, say:
    Code:
    #include <math.h>
    int round_to_even ( double d )
    {
        int rv = (int)d;
        if ( (rv &#37; 2) == 0 )
            return rv;
        else
            return 1 + rv;
    }
    Since there are a couple ways to round correctly, actually.
    Last edited by whiteflags; 02-12-2008 at 10:16 PM.

  5. #5
    Registered User
    Join Date
    Jan 2008
    Posts
    19
    Hey thanks.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by blackcell View Post
    So if I specify a variable as an integer and only want to work with whole numbers, what happens if the user inputs 99.7 ?

    If nothing happens it would be safe to say I could round(var); to achieve my desired results?
    You'll also need to be careful how you are inputting your numbers. If you're using %d to read into an int, for example, and the user types 99.7, you're in a lot of trouble. For %d knows what an int is, and therefore when it sees the . it will stop, putting 99 in the int variable and leaving the .7 out to dry (which means there's no way to round to 100 here, since even the fact that there was a decimal is lost). And if you're not careful, every successive call to scanf will then fail, since that .7 will still be there gumming up the works.

    If you need to do input validation, you can search here for it; I seem to remember a couple threads in the not too distant past about how to deal with nefarious users.

  7. #7
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    What you could do is just print the number into a string, then search along for the '.' and look at the number after the '.' Then make the dot a Null (zero) and read the string back into an integerthen increase that number if necessary.
    Might not be to everyones liking as the best way to do it, but at least it works
    And can be done in 2 minutes

  8. #8
    Banned
    Join Date
    Nov 2007
    Posts
    678
    as simple as it gets:
    Code:
    float f;
    // . . .
    int r = (int)(f + 0.5f);

  9. #9
    Registered User
    Join Date
    Dec 2006
    Posts
    14
    Quote Originally Posted by citizen View Post
    Truncation.

    int d = 99.7 results in 99.

    However, you could write a round function easily, say:
    Code:
    #include <math.h>
    int round_to_even ( double d )
    {
        int rv = (int)d;
        if ( (rv % 2) == 0 )
            return rv;
        else
            return 1 + rv;
    }
    Since there are a couple ways to round correctly, actually.
    Friend will it work for d = 98.7 ?

    i think we should do it as:
    Code:
    #include <math.h>
    int round_to_even ( double d )
    {
        float rv = d - (int)d;
        if ( (rv < 5 )
            return rv;
        else
            return 1 + rv;
    }

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    That has problems too. It will return a small number like 8 for most inputs.

    According to wikipedia, this is the round-to-even method:
    • Decide which is the last digit to keep.
    • Increase it by 1 if the next digit is 6 or more, or a 5 followed by one or more non-zero digits.
    • Leave it the same if the next digit is 4 or less
    • Otherwise, if all that follows the last digit is a 5 and possibly trailing zeroes; then change the last digit to the nearest even digit. That is, increase the rounded digit if it is currently odd; leave it if it is already even.

    So it turns out that I did it wrong, but it's easy to do right. You need another variable for the fractional part so you can check that according to the method. And I would probably use the fmod function in math.h to separate a double's fractional part from its whole integer part.

  11. #11
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by manav View Post
    as simple as it gets:
    Code:
    float f;
    // . . .
    int r = (int)(f + 0.5f);
    Actually, that, as it is written will not work at all.
    Try it! You will see some odd results!!

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Actually, that, as it is written will not work at all.
    Try it! You will see some odd results!!
    I have tried it and, on the MinGW port of gcc 3.4.5 with Windows XP SP2, there were no odd results as you claimed. Kindly provide your test program, input, output and expected output.

    My own test was:
    Code:
    #include <stdio.h>
    #include <assert.h>
    
    int round_nearest(float f);
    
    int main(void)
    {
        assert(round_nearest(0.0f) == 0);
        assert(round_nearest(0.001f) == 0);
        assert(round_nearest(0.499f) == 0);
        assert(round_nearest(0.5f) == 1);
        assert(round_nearest(0.501f) == 1);
        assert(round_nearest(0.999f) == 1);
        assert(round_nearest(1.0f) == 1);
        assert(round_nearest(1.001f) == 1);
        assert(round_nearest(1.499f) == 1);
        assert(round_nearest(1.5f) == 2);
        assert(round_nearest(1.501f) == 2);
        assert(round_nearest(1.999f) == 2);
        assert(round_nearest(2.0f) == 2);
        assert(round_nearest(2.001f) == 2);
        return 0;
    }
    
    int round_nearest(float f)
    {
        return (int)(f + 0.5f);
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by laserlight View Post
    I have tried it and, on the MinGW port of gcc 3.4.5 with Windows XP SP2, there were no odd results as you claimed. Kindly provide your test program, input, output and expected output.

    My own test was:
    Code:
    #include <stdio.h>
    #include <assert.h>
    
    int round_nearest(float f);
    
    int main(void)
    {
        assert(round_nearest(0.0f) == 0);
        assert(round_nearest(0.001f) == 0);
        assert(round_nearest(0.499f) == 0);
        assert(round_nearest(0.5f) == 1);
        assert(round_nearest(0.501f) == 1);
        assert(round_nearest(0.999f) == 1);
        assert(round_nearest(1.0f) == 1);
        assert(round_nearest(1.001f) == 1);
        assert(round_nearest(1.499f) == 1);
        assert(round_nearest(1.5f) == 2);
        assert(round_nearest(1.501f) == 2);
        assert(round_nearest(1.999f) == 2);
        assert(round_nearest(2.0f) == 2);
        assert(round_nearest(2.001f) == 2);
        return 0;
    }
    
    int round_nearest(float f)
    {
        return (int)(f + 0.5f);
    }
    OK maybe it does work, however I was a bit confused about the 0.5f bit, I thought this
    was 0.5*f, which obviously would not work.
    OK so it seems the "f" means it is a float which I can't say I have ever used before.
    So the next question is why do you put an "f" after the numbers?
    It seems to work well without the f? I guess that is what confused me, as I said, initially
    I thought he meant 0.5*f because I don't see why he needs to put an "f" there at all.

    Anyway it does look very confusing to anyone who is used to normal mathematical
    expressions!!

    What is wrong with?
    Code:
    int round_nearest(float f)
    {
        return (int)(f + 0.5);
    }
    Last edited by esbo; 02-16-2008 at 03:45 AM.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    So the next question is why do you put an "f" after the numbers?
    It seems to work well without the f? I guess that is what confused me, as I said, initially
    I thought he meant 0.5*f because I don't see why he needs to put an "f" there at all.
    Floating point literals are of type double unless specified as float by the case-insensitive f suffix. In this case the numbers should be in range of both double and float, so it does not matter either way.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Rounding off a double
    By C-Dummy in forum C Programming
    Replies: 3
    Last Post: 06-23-2008, 11:45 AM
  2. setprecision() - can I count on it rounding or not?
    By major_small in forum C++ Programming
    Replies: 2
    Last Post: 11-23-2005, 02:26 PM
  3. Rounding errors
    By Buckshot in forum C++ Programming
    Replies: 15
    Last Post: 08-16-2005, 09:11 PM
  4. preventing rounding problems with doubles
    By mccoz in forum C++ Programming
    Replies: 9
    Last Post: 11-05-2004, 09:23 AM
  5. Help with rounding a number
    By nickk in forum C Programming
    Replies: 3
    Last Post: 06-02-2004, 11:44 AM