%16 with double

This is a discussion on %16 with double within the C Programming forums, part of the General Programming Boards category; can't i mod a double ? Code: #include<stdio.h> int main() { double a=100; printf("%d",a%16); return 0; } and i get: ...

  1. #1
    Registered User
    Join Date
    Dec 2005
    Posts
    167

    %16 with double

    can't i mod a double ?
    Code:
    #include<stdio.h>
    
    int main()
    {
            double a=100;
            printf("%d",a%16);
            return 0;
    }
    and i get:
    Code:
    root@cactus:~/PL# gcc -o mod mod.c
    mod.c: In function ‘main’:
    mod.c:6: error: invalid operands to binary %

  2. #2
    cwr
    cwr is offline
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    868
    Evidently not. modulus only makes sense for integer divisions. You could cast it to an int first.

  3. #3
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40
    Quote Originally Posted by spank
    can't i mod a double ?
    Code:
    #include<stdio.h>
    
    int main()
    {
            double a=100;
            printf("%d",a%16);
            return 0;
    }
    and i get:
    Code:
    root@cactus:~/PL# gcc -o mod mod.c
    mod.c: In function ‘main’:
    mod.c:6: error: invalid operands to binary %
    Isn't a double a floating point? I'm a C total n00b so I might be wrong but as far as I am aware...

    1) When you assign a value to a float, you have to add a decimal point to the assigned value.
    2) The signifier for a double is %lf. You have put in %d which I believe is for int
    3) I think I read somewhere that double is not always available and it depends on the system you are using.

    Could it be that one of these things is causing the problem? Maybe someone with more experience can say for sure. In my short time here, people have been incredibly helpful and knowledgable, I'm sure someone will be able to point out the problem.

    Hope this helps,
    TV

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,422
    Code:
    SYNOPSIS
           #include <math.h>
    
           double fmod(double x, double y);
    
           float fmodf(float x, float y);
    
           long double fmodl(long double x, long double y);
    
    DESCRIPTION
           The  fmod()  function  computes the remainder of dividing x by y.  The return value is x - n * y,
           where n is the quotient of x / y, rounded towards zero to an integer.

  5. #5
    cwr
    cwr is offline
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    868
    Quote Originally Posted by tvsinesperanto
    Isn't a double a floating point? I'm a C total n00b so I might be wrong but as far as I am aware...

    1) When you assign a value to a float, you have to add a decimal point to the assigned value.
    Not really, you need a decimal point for an expression like float f = 1/2.0; because otherwise 1/2 is integer and evaluates to 0 instead of the desired 0.5. Something like float f = 2; is fine. However, it would be good practice when initialising a floating point type to add the .0 for clarity.

    2) The signifier for a double is %lf. You have put in %d which I believe is for int
    Actually with printf, doubles use %f. %lf is only valid for scanf. This is because floats and doubles both become doubles when passed to printf.

    3) I think I read somewhere that double is not always available and it depends on the system you are using.
    Any conforming C compiler will have the double type.

  6. #6
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40
    Quote Originally Posted by cwr
    Not really, you need a decimal point for an expression like float f = 1/2.0; because otherwise 1/2 is integer and evaluates to 0 instead of the desired 0.5. Something like float f = 2; is fine. However, it would be good practice when initialising a floating point type to add the .0 for clarity.
    Ah, OK. My text book says that you "should always put in the decimal point". I took that to mean that it was required but I see now that it could be read as a suggestion. Thanks for putting me straight on that.

    Quote Originally Posted by cwr
    Actually with printf, doubles use %f. %lf is only valid for scanf. This is because floats and doubles both become doubles when passed to printf.
    Ok, so does that mean that, when using a double in a printf() function, you must use %f and can't use %lf or that it makes no difference whether you use %lf or %f?

    Referring, once again, to my text book, it seems to imply that you should use %lf. It actually says...

    "These [referring to a table below that contains a list of signifiers and their corresponding types in which %lf is matched to double] are used in all *f() functions: printf(), scanf(), fprintf(), sscanf(), sprintf(), and so forth."*

    * Pg 368 "C Programming" by Larry Ullman and Marc Liyanage

    So, is the text incorrect then? I am starting to have concerns about my text book if this is the case.

    Quote Originally Posted by cwr
    Any conforming C compiler will have the double type.
    This was actually my mistake this time, I simply misread the book. It actually says that a long double is not always available. Sorry about that.

    Sorry to hijack the thread like this but I am concerned that my text book may be steering me wrong in places. Should I start a new thread perhaps?

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    Ok, so does that mean that, when using a double in a printf() function, you must use %f and can't use %lf or that it makes no difference whether you use %lf or %f?
    The former: you must use %f. %lf is invalid for printf(). (But you must use %lf for scanf(); %f in scanf() reads a float instead of a double.)

    Your book is a bit misleading. Which one is it?
    [edit]
    Never mind, I see you posted its title.
    [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    It actually says that a long double is not always available.
    long double should be around on newer compilers, like Dev-C++. It's part of the C99 standard.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40
    Quote Originally Posted by dwks
    The former: you must use %f. %lf is invalid for printf(). (But you must use %lf for scanf(); %f in scanf() reads a float instead of a double.)

    Your book is a bit misleading. Which one is it?
    [edit]
    Never mind, I see you posted its title.
    [/edit]
    Yeah, I am really impressed with the layout and the way it explains things but I'm now quite concerned that it may contain erorrs.

    Oh well, I guess that is what forums are for...

    Thanks for the help.

    Cheers,
    TV

  10. #10
    Registered User
    Join Date
    Aug 2005
    Posts
    1,267
    This is because floats and doubles both become doubles when passed to printf.
    That actually applies to any function whever passing a float by value. The compiler expands a float to double, push the double on the stack, then in the receiving function that declares it as a float in the parameter list, the compiler has to shrink it back to a float. Programs that may be speed critical should just use doubles everywhere to avoid all those conversions.

  11. #11
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Quote Originally Posted by Ancient Dragon
    That actually applies to any function whever passing a float by value. The compiler expands a float to double, push the double on the stack, then in the receiving function that declares it as a float in the parameter list, the compiler has to shrink it back to a float. Programs that may be speed critical should just use doubles everywhere to avoid all those conversions.
    I'd be interested in more information on this. Some of my googling has led me to things such as "default argument promotions" and "when a function is called with no prototype in scope" and stuff about K&R1 vs C89. I'll continue digging, but if you have quickie links I would be grateful.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  12. #12
    cwr
    cwr is offline
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    868
    Quote Originally Posted by Ancient Dragon
    That actually applies to any function whever passing a float by value. The compiler expands a float to double, push the double on the stack, then in the receiving function that declares it as a float in the parameter list, the compiler has to shrink it back to a float. Programs that may be speed critical should just use doubles everywhere to avoid all those conversions.
    Are you talking about the specific behaviour of one architecture, or are you saying this happens generally?

    Edit: Followup:

    I made this simple program below that calls a function taking a float many many times...
    Code:
    #include <stdio.h>
    float foo(float f)
    {
        return f+1.0;
    }
    int main(void)
    {
        int i;
        float f = 0;
        for (i = 0; i < 100000000; i++)
            f = foo(f);
        printf("%f", foo);
        return 0;
    }
    I then timed it:
    Code:
    $ gcc -o float float.c
    $ for ((i=0; i<5; i++)); do time ./float; done 2>&1 | grep real
    real    0m1.110s
    real    0m1.098s
    real    0m1.097s
    real    0m1.108s
    real    0m1.097s
    I then replaced the above code to use doubles everywhere instead of float:
    Code:
    $ cat float.c | sed 's/float/double/g' > double.c
    $ gcc -o double double.c
    $ for ((i=0; i<5; i++)); do time ./double; done 2>&1 | grep real
    real    0m4.235s
    real    0m4.325s
    real    0m4.390s
    real    0m4.301s
    real    0m4.270s
    Here we see double is much slower. Let's try with -O2:
    Code:
    $ gcc -O2 -o float float.c
    $ for ((i=0; i<5; i++)); do time ./float; done 2>&1 | grep real
    real    0m0.931s
    real    0m0.923s
    real    0m0.933s
    real    0m0.923s
    real    0m0.933s
    $ gcc -O2 -o double double.c
    $ for ((i=0; i<5; i++)); do time ./double; done 2>&1 | grep real
    real    0m0.934s
    real    0m0.922s
    real    0m0.935s
    real    0m0.922s
    real    0m0.933s
    The timing is now basically identical. I'm not sure there is any significant overhead for function calls with double versus float?

    Oh, the above timings are on a Pentium 4 3.0Ghz using gcc 3.3 under linux 2.6. I did have a look at the assembly output, but my x86 asm is a little rusty, so I couldn't really comment constructively.

    Update:

    Here are the same timings with -O2 using gcc 4.0 and a PowerPC (ppc) G4 1.0GHz under MacOS X 10.4:
    Code:
    $ for ((i=0; i<5; i++)); do time ./float ; done 2>&1 | grep real
    real    0m4.170s
    real    0m4.212s
    real    0m4.071s
    real    0m4.187s
    real    0m4.096s
    $ for ((i=0; i<5; i++)); do time ./double ; done 2>&1 | grep real
    real    0m2.754s
    real    0m3.216s
    real    0m3.023s
    real    0m2.797s
    real    0m2.762s
    Here we see double is indeed faster, but this may also be to do with the add operation, not just the function call overhead.
    Last edited by cwr; 03-05-2006 at 09:39 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Copying 2-d arrays
    By Holtzy in forum C++ Programming
    Replies: 11
    Last Post: 03-14-2008, 03:44 PM
  2. Conversion From C++ To C
    By dicon in forum C++ Programming
    Replies: 2
    Last Post: 06-10-2007, 02:54 PM
  3. need some help with last part of arrays
    By Lince in forum C Programming
    Replies: 3
    Last Post: 11-18-2006, 08:13 AM
  4. newbie needs help with code
    By compudude86 in forum C Programming
    Replies: 6
    Last Post: 07-23-2006, 08:54 PM
  5. Unknown Math Issues.
    By Sir Andus in forum C++ Programming
    Replies: 1
    Last Post: 03-06-2006, 05:54 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21