Thread: fmod vs. modf vs. floor

  1. #1
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413

    fmod vs. modf vs. floor

    Probably a trivial question, but what would be the best/fastest way to get the fractional part of a float?

    can do...
    double tmp = a * b;
    tmp -= floor(tmp);

    or

    fmod(a * b, 1.0);

    or

    modf(a * b, void);

  2. #2
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    I dunno, but you could write a simple program to test it.

    I think your first version would have problems with negative numbers though. AFAIK floor would set -4.5 to -5. If thats the case you should cast to int instead like: tmp -= (int)tmp;

  3. #3
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413
    I should've mentioned, I was only concerned with positive values.

  4. #4
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Well I think that flooring and subtracting would be faster than fmod, and casting to int would be faster than calling floor. But thats just what I would expect.

  5. #5
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413
    Hmmm...yes, but you'd have to cast back to double to subtract.

    Btw, love the title of your new website..."Code & S__t"

  6. #6
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    I would expect modf to be fastest, because it is designed to do specifically what you ask. Judging by the glibc implementation of modf, I'd say this is the case. It does some simple bit manipulations that essentially copies out the fractional part.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by DoctorBinary View Post
    I would expect modf to be fastest, because it is designed to do specifically what you ask. Judging by the glibc implementation of modf, I'd say this is the case. It does some simple bit manipulations that essentially copies out the fractional part.
    I'll have to look at that one day. Piqued my curiosity in a perverse manner.

    Presumably that working is based on the floating value being in some specified range (magnitude less than some threshold). Not all floating point values (eg with a large exponent) will even have a fractional part.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by grumpy View Post
    I'll have to look at that one day. Piqued my curiosity in a perverse manner.

    Presumably that working is based on the floating value being in some specified range (magnitude less than some threshold). Not all floating point values (eg with a large exponent) will even have a fractional part.
    Those are the easy ones: return 0.

  9. #9
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413
    Quote Originally Posted by DoctorBinary View Post
    I would expect modf to be fastest, because it is designed to do specifically what you ask. Judging by the glibc implementation of modf, I'd say this is the case. It does some simple bit manipulations that essentially copies out the fractional part.
    Do you absolutely have to assign the integral part to another value though? Can I just stick void in there or something? I'm only interested in the fractional part.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Epy View Post
    Do you absolutely have to assign the integral part to another value though? Can I just stick void in there or something? I'm only interested in the fractional part.
    You have to pass a valid pointer in there, but you are not required to care about it.

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    I did a quick performance test on Windows (Visual C++) and, of the three methods -- modf, fmod, and floor -- floor ran faster than modf, and both ran much faster than fmod.

    Of course I don't have the source code for Windows, but looking at the glibc source for floor, it does "bit twiddling" just like modf. Maybe it's faster because it doesn't pass the extra parameter? I don't know.

    One thing that may be an issue with the floor method is floating point round off error. You have to subtract out the floor to get the fractional part. modf just extracts it directly. I'll have to think about this some more...

  12. #12
    Make Fortran great again
    Join Date
    Sep 2009
    Posts
    1,413
    Excellent, thanks Doc. Floor(x) it is.

  13. #13
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    I still think casting would be quicker as you have to deal with function overhead.

    Heres the prog I used:
    Code:
    #include <stdio.h>
    #include <math.h>
    
    int main(){
            float num = 12.5678, ans;
            int i;
            for(i=0; i<10000000; i++){
                    //ans = num-((int)num);  //use cast
                    ans = num-floor(num);   //use floor
            }
            printf("%f\n", ans);
            return 0;
    }
    Its very crude. These were my typical timed results:

    using floor:
    real 0m0.468s
    user 0m0.468s
    sys 0m0.000s
    using cast:
    real 0m0.163s
    user 0m0.140s
    sys 0m0.008s
    When I compiled with 02 optimisations the prog ran in 0.004s, but I'm guessing the optimiser removed the redundant operations.

  14. #14
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    I added a "cast" testcase and indeed it ran faster than floor (though not a big difference like you saw mike_g). I was using doubles though (with a cast to "long long" to match).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Elevator Function confusion
    By applescruff in forum C++ Programming
    Replies: 5
    Last Post: 12-16-2004, 10:14 AM
  2. FMOD implimentation, how'd you do it?
    By Jeremy G in forum Game Programming
    Replies: 10
    Last Post: 06-12-2004, 12:04 AM
  3. floor & floorf
    By chrismiceli in forum C Programming
    Replies: 1
    Last Post: 08-09-2003, 10:58 PM
  4. Problem using floor() function
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 05-02-2002, 04:15 PM
  5. Newbie working on a lift simulation
    By dethray79 in forum C++ Programming
    Replies: 1
    Last Post: 10-07-2001, 08:28 AM