Thread: Typecasting and math function

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    3

    Typecasting and math function

    Hello

    I am very confused at my problem. I have a piece of code that sometimes offers the correct result, and sometimes not.

    The code is similar to this
    Code:
    #include "cmath"
    #include "iostream"
    using namespace std;
    
    int log(int a){
        return (int)log2(a+1);
    }
    
    int main(){
    int a =7;
    cout << log(a) << endl;
    }
    for a = 7 this returns 2 instead of 3.
    for a = 15 it returns the correct value of 4
    it seems to alternate for other powers of two.

    I programmed using g++ on ubuntu which gave me some form of converting double to int warning which I managed to suppress by typecasting (int). However when I went to test my program on windows using cygwin the (int) seems to be the cause of error.

    Code:
    in windows:
    int a = 7;
    cout << log2(a+1) << endl; gives 3 
    cout << (int)log2(a+1) << endl; gives 2
    What is the cause of this?

    thanks

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    2.99...99
    printed as double will probalbly shown 3
    (int)2.99...99 will give you 2
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    vart is right. The solution would be to do:
    Code:
    return (int)(log2(a+1) + epsilon);
    Where epsilon is a small value, eg. 1e-12.

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    3
    Thanks you are right adding epsilon works.

    Why would the math function return 2.999 instead of 3 Can I blame the compiler?
    Last edited by wozaa; 03-18-2009 at 12:20 PM.

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by wozaa View Post
    Thanks you are right adding epsilon works.

    Why would the math function return 2.999 instead of 3 Can I blame the compiler?
    float arithmetic is not precise. to calculate log2 probably some long sum is used, which is stopped as soon as some predefined precision is achieved. so any float point operaton result could be a little less or bigger than presize result. you should take this into account.

    This is one of the resons not to use == on float types
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    Registered User
    Join Date
    Mar 2009
    Posts
    3
    Quote Originally Posted by vart View Post
    float arithmetic is not precise. to calculate log2 probably some long sum is used, which is stopped as soon as some predefined precision is achieved. so any float point operaton result could be a little less or bigger than presize result. you should take this into account.

    This is one of the resons not to use == on float types
    Thanks, makes sense.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by vart View Post
    float arithmetic is not precise. to calculate log2 probably some long sum is used, which is stopped as soon as some predefined precision is achieved. so any float point operaton result could be a little less or bigger than presize result. you should take this into account.

    This is one of the resons not to use == on float types
    Actually, on a processor with floating point, it's likely that log2 is simply log(x) / log(2) - but either way, the result is not EXACT.

    If you really just want log2 to the nearest integer value, you could use a method of figuring out the highest bit - there are several ways to do that, but this works:
    Code:
    int log(int x)
    {
        int cnt = -1;  
        x ++;   // Make it x + 1 first. 
        do
        {
           cnt++;
           x >>= 1;
        } while(x);
        return cnt;
    }
    Note that the above code doesn't work for negative numbers (neither does log).
    --
    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