Thread: efficiency comparing ints and floats

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    efficiency comparing ints and floats

    I guess this is a laziness question about how many times I have to type ".0". If I'm comparing a floating point variable to an integer value, like:
    Code:
    if (Rotation==360)
    will the processor end up having to perform some additional conversion to do the comparison?, as opposed to
    Code:
    if (Rotation==360.0)
    or can I just expect the compiler is smarter than that?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Rule 1 - don't compare for equality
    http://c-faq.com/fp/fpequal.html

    Why are YOU concerned with such microscopic optimisations?

    Look at the ASM
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    This raises another question, naturally (and thanks for that tip). I presume it only applies if the float is the product of some operation which could give it any number of decimal places? In reality, this number
    Code:
    if (Rotation==360)
    is always an integer because the only thing that ever happens to it is it gets incremented or decremented by 1. It's a float because it's used by a function that expects a float and this seems easier than casting it (is that a mistake?) Anyway, the comparison should be okay then, right?

    As for the "micro-optimization", well it just occurred to me that by not bothering to add the .0 I might just as well (for all I know) throw in some extra trig functions or something (for no good reason), which means all my fine algorithmic thinking will be wasted.

    But no, I won't look at the ASM. I never look at the ASM. Where is the ASM?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Look at the ASM
    Exactly.

    It appears that the following code compiles into exactly the same thing whether you have 360.0 or 360:

    Code:
    int main(void)
    {
        double d = 1.0;
        if (d == 360) {
            d = 0.0;
        }
        return 0;
    }
    I don't see any reason why the compiler shouldn't realize that the literal 360 is compared against a double and therefore replace it with 360.0 for you.

    Rule 1 - don't compare for equality
    But what if all the calculations I do with the float only involve operations and values that can be represented precisely? (E.g, if I know I will be only adding or subtracting 0.25, 0.5 or 0.75 from small values.)

    Where is the ASM?
    I think it is the thing that you get when you do:

    Code:
    gcc a.c -S -o a.txt
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > But what if all the calculations I do with the float only involve operations and values that can be represented precisely?
    I think it would be a dangerous habit to get used to.

    Sure it might work for a while, but then you'll use it for something you shouldn't, and won't remember the reasons why it was OK in the special case.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by anon View Post
    But what if all the calculations I do with the float only involve operations and values that can be represented precisely?
    That's what I'm asking in the last post (when I said "is always an integer", I meant an integer, not a C int). You could check this one by printing all the bits out, I think, but I won't bother doing that either. I'm sure if the number has a fixed precision it will be okay.

    Oh -- and thank you oh so much (!!) for finding that assembly code for me...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by MK27 View Post
    That's what I'm asking in the last post (when I said "is always an integer", I meant an integer, not a C int). You could check this one by printing all the bits out, I think, but I won't bother doing that either. I'm sure if the number has a fixed precision it will be okay.

    Oh -- and thank you oh so much (!!) for finding that assembly code for me...
    So you actually know what formats can exactly be represented exactly by floating point values? Wow.
    Because I don't. I don't even think the standard does - I'm pretty sure it doesn't. Since it's implementation defined.

    On most implementations, however, I can tell you even the simple number "0.1" can't be represented exactly. Surprised? Then don't use exact float comparison in any situation. Not surprised? Then still don't use exact float comparison in any situation.

    Sorry, but the entire fact you say you 'know' that comparing exactly is legal in your case makes me think that you don't know enough about all of this to know whether it's legal.

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    So you actually know what formats can exactly be represented exactly by floating point values? Wow.
    Because I don't. I don't even think the standard does - I'm pretty sure it doesn't. Since it's implementation defined.
    No expert here but from the IEzzz standard or whatever it is called, which seems to be rather universally used (except perhaps for strange and exceptional architectures) it should follow that integers in a certain range (I think a lot larger than 32-bit int for doubles) as well as fractional values that are (negative) powers of two and their sums up to some precision can be represented precicely: e.g 0.5, 0.25, 0.75, 0.125, 0.625 etc. Not all floating point values are approximations.

    0.1, though, cannot indeed be represented precisely in this standard.

    It would seem to me that as long as you can guarantee that your float values indeed hold integral values (no calculations that would violate that, e.g you know that all operations are additions or substractions in a relatively small range), you might be quite safe with such comparisons.

    So the question is, whether you should use integers and cast them to floats as the API requires, or use floats to begin with - even though you only want them to store integral values. I guess there is no single answer - it would largely depend on what you do with the variables, how often you pass them to functions etc. Only way to know is to try it both ways and profile the performance in either case. (You can use a typedef that can be either float or int and use that for all such variables - assuming your program is correct in the first place with floats - e.g no integer division: then trying both ways might mean changing just one line and recompiling.)

    I wouldn't be rather surprised if you find that this doesn't matter. If a program feels slow, either it simply has to do so much work that any micro-optimization won't make any noticeable difference (there's no difference between waiting 4950 or 5000 ms for an operation to complete), or you can make a large-scale optimization (use a better algorithm/data representation scheme - and that's not just variable types) bringing the time of the operation perhaps down to 2500 or even 500 ms or less and really making a discernible difference.

    If you use an algorithm with bad complexity and I know a better algorithm then you can micro-optimize all you want, your C program is not going to beat my Python program (which might be about 30 times slower than C at raw number crunching - tested with determining primeness with the same algorithm) for sufficiently large input.

    I also believe there is not much point in creating a small test program and testing the efficiency of a single operation by itself. While you may see that one way is 200% faster than the other, in a real program and with real workload this particular operation may be taking 0.01% of total execution time, so reducing that 200% wouldn't make much of a difference.
    Last edited by anon; 02-28-2009 at 08:06 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Thanks for reminding me of this important point about doing math with fixed precision numbers in C, gang.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Also, if you are worried about micro-optimizations, then you are doing something else wrong, as well.
    if (x == 10.0)
    If x is a float, then x will be promoted to a double, and then compared. Oops.
    Learn to distinguish floats and doubles!
    if (x == 10.0f)
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Elysia View Post
    If x is a float, then x will be promoted to a double, and then compared. Oops.
    Learn to distinguish floats and doubles!
    if (x == 10.0f)
    Did not know that! Thanks again Elysia!
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by EVOEx View Post
    So you actually know what formats can exactly be represented exactly by floating point values? Wow.
    Because I don't. I don't even think the standard does - I'm pretty sure it doesn't. Since it's implementation defined.

    On most implementations, however, I can tell you even the simple number "0.1" can't be represented exactly. Surprised? Then don't use exact float comparison in any situation. Not surprised? Then still don't use exact float comparison in any situation.

    Sorry, but the entire fact you say you 'know' that comparing exactly is legal in your case makes me think that you don't know enough about all of this to know whether it's legal.
    It is possible to know what values on a particular platform can be represented exactly. Seeing as how I've written my own mega floating point class before that is stored and works identically to float on an x86 CPU, I'm pretty confident that I know what can and cant be represented.
    As for MK27, I'm not sure.
    Anyway, the issue here applies regardless of whether there is an exact float comparison going on. He could have written Rotation < 360. The answer should be that it makes no diference whether it is written as 360, 360.f, or 360.0, it's about as easy for a compiler to work out which is best at compile time, as adding 1+1 is. Just write whatever you like.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by iMalc View Post
    It is possible to know what values on a particular platform can be represented exactly. Seeing as how I've written my own mega floating point class before that is stored and works identically to float on an x86 CPU, I'm pretty confident that I know what can and cant be represented.
    As for MK27, I'm not sure.
    Anyway, the issue here applies regardless of whether there is an exact float comparison going on. He could have written Rotation < 360. The answer should be that it makes no diference whether it is written as 360, 360.f, or 360.0, it's about as easy for a compiler to work out which is best at compile time, as adding 1+1 is. Just write whatever you like.
    However, to avoid simple compilers doing the wrong thing, using 360.0f or 360.0 depending on whether rotation is a double or float will not HURT. It is at the most three characters more, and almost certain to NEVER be worse than what the compiler comes up with. Bear in mind tho', that if you DO change rotation to be an integer, then 360.0 WILL mean that the compiler converts the integer value to a double, which is never a good plan.

    Also, do not be tempted to try to make it faster with:
    Code:
    if ((int)rotation == 360)
    It is valid converting a float to integer this way, and if that's what you really want, fine. However, it is absolutely certainly not faster (at least not on hardware that has floating point operations), since converting float to integer is slower than comparing a constant float with another float value.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by EVOEx View Post
    So you actually know what formats can exactly be represented exactly by floating point values? Wow.
    Because I don't. I don't even think the standard does - I'm pretty sure it doesn't. Since it's implementation defined.
    Any floating point implementation that can't represent integral values exactly is broken. You would have to deliberately go out of your way to design an implementation where this was not the case, and I can't imagine any benefit from doing so.

    If the value is always an integer, then I question the use of a floating point type to store it, but I would not worry about the equality check. It's kind of unclear, though.

    EDIT: I would assume that the comparison in question is part of some code that looks like this:

    Code:
    if(rotation == 360)
    {
        // make sure angle stays between 0 and 360
        rotation = 0;
    }
    But I would never write it that way -- I'd do this:

    Code:
    if(rotation >= 360.0)
    {
        rotation -= 360.0;
    }
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Obviously, very LARGE integer values can not be represented exactly (the last digits turn to zeros, generally), but I do agree that integer values in the range that is represented in the mantiass (that is, for float 2^23 or so, and 2^53 or so for double) should be possible to represent precisely.

    That in itself doesn't mean that you can't get inprecise values even if the value itself can be represented exactly. Whenever you use add or subtract on floating point values, both numbers need to be "the same exponent". So if you have a very large number, and try to add/subtract a very small number, the small number will first be multiplied up to match the large number. Of course, this means that if you then subtract the large number again, some of the smaller parts may have gone missing in the processing.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ints & floats
    By BEN10 in forum C Programming
    Replies: 4
    Last Post: 02-28-2009, 03:41 PM
  2. Replies: 15
    Last Post: 12-17-2008, 12:11 AM
  3. determining floats or ints
    By quiet_forever in forum C++ Programming
    Replies: 3
    Last Post: 04-15-2007, 07:11 PM
  4. reading int's and floats...
    By flightsimdude in forum C Programming
    Replies: 8
    Last Post: 09-20-2003, 01:17 PM
  5. Replies: 2
    Last Post: 08-05-2002, 02:19 PM