Thread: Most Efficient Way to Check a Variable Is A Whole Number

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    127

    Most Efficient Way to Check a Variable Is A Whole Number

    Hi,

    I have a question. Say you have a variable of type double, and you want to check if it is a whole number or not. What is the most efficient way to do this? At present I am doing something like this, but it doesn't seem very efficient.

    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
        double a_dbl = 3.5;
        int a_int = static_cast<int>(a_dbl);
    
        if (a_dbl == a_int)
            cout << "a_dbl is a whole number";
        else 
            cout << "a_dbl is not a whole number";
    }
    Thanks guys.

  2. #2
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    I think "static_cast<int>(a_dbl) == 3". (Probably rounded down)
    Why is it inefficient?

  3. #3
    Registered User
    Join Date
    Feb 2009
    Posts
    42
    The cast will round it down as it basically cuts off the decimal part of the number.
    The code seems fine though.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    What sort of "efficiency" are you asking for - performance (e.g. smaller or faster code), or simply "easier to type in" efficient?

    If you need to do A HUGE number of "is this a whole number", then you may want to use optimized code. But if you simply want to know if it's OK to do it this way, I'd say it's as good as you can get.

    There are problems converting numbers to integer and back to float if they are borderline the range that the floating point type can hold. For example, a float will run out of precision at about 2^23. So if you have a number that is more than 32 million (or less than -32 million), then it won't match precisely.

    A double can hold 2^53 bits, so it's a fairly huge value before it starts loosing precision, but it's possible if you are counting very large amounts (national debts and such things).

    --
    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.

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    It is both inefficient and fails for anything but a fairly small range with respect to the actual range of a double. 10 billion isn't a whole number with that code!
    The correct way to do it would be:
    Code:
        if (a_dbl == floor(a_dbl))
    Or you can just as easily use 'ceil' if you prefer, which is 1 character shorter.
    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"

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    127
    I thought it might be inefficient because it's using an int variable as well as the original double. ie I thought it would be more efficient not to use the extra one.

    BTW if I use if
    Code:
    (a_dbl == floor(a_dbl))
    do I need to include another header file for that?

    Thanks.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by bengreenwood View Post
    I thought it might be inefficient because it's using an int variable as well as the original double. ie I thought it would be more efficient not to use the extra one.

    BTW if I use if
    Code:
    (a_dbl == floor(a_dbl))
    do I need to include another header file for that?

    Thanks.
    You need math.h, which you probably need if you are doing anything but simple math problems.

    --
    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.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Be careful when using == to compare floating point numbers. See these FAQ entries:

    [29.16] Why is floating point so inaccurate? Why doesn't this print 0.43?
    [29.17] Why doesn't my floating-point comparison work?

    For example, on my machine, the following code:
    Code:
    #include <iostream>
    #include <cmath>
    
    int main()
    {
       float a = 1000.43f;
       float b = 1000.0f;
       float c = a - b;  // 0.43
       float d = c*100.f;  // 43
    
        if (d == std::floor(d))
            std::cout << d << " is equal to " << std::floor(d) << ", so it is a whole number!!\n";
        else
            std::cout << d << " is not equal to " << std::floor(d) << ", so it is NOT a whole number!!\n";
    }
    outputs the wrong answer:
    Code:
    42.9993 is not equal to 42, so it is NOT a whole number!!
    Whether you get the same result depends on your compiler, but seemingly simple computation can give the incorrect answer if you're not careful.

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    If we make the reasonable assumption that floating point values can precisely represent integer values (a likely, but by no means guaranteed assumption), then there are myriad ways to do this, most of which have already been mentioned.

    As far as which is more efficient, any one of the proposed methods: conversion to integer, ceil, floor, other rounding -- is going to involve a processor-specific sequence of instructions whose performance can't be predicted in advance. What is most efficient on one processor may be less efficient on another, even between revisions of the same basic line of CPU.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    If the problem is changed to "Is this close enough to a whole number" then one solution is this:
    Code:
        if (fabs(a_dbl - std::floor(a_dbl)) < EPSILON || fabs(a_dbl - std::ceil(a_dbl)) < EPSILON)
    Where EPSILON is a value that is chosen to be suitable for the floating point representation being used.
    The expression may be able to be simplified though.
    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"

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Daved View Post
    Be careful when using == to compare floating point numbers.
    While, in general, I agree with you ..... it's not necessary to worry when comparing x and floor(x) if it is necessary to detect that a floating point variable x holds an integral value.

    However, in practice, if the value is being read from a user (eg as input from stdin) it would be better to read a string and then interpret the content of the string to see if it represents an integral value. That eliminates concerns with rounding of floating point values. The basic procedure to do this would be

    1) If there is a decimal point, count the number of digits after the decimal point.

    2) Extract the exponent, if any (eg 1.3E2 has an exponent of 2).

    3) Take the difference. If result is positive, the value is not integral.

    Examples

    100 0 after decimal, 0 exponent. Result: 0 i.e. integral
    0.1 1 after decimal, 0 exponent. Result 1: i.e. non-integral.
    0.1E2 1 after decimal, 2 exponent Result -1 i.e. integral
    100E-3 0 after decimal, -3 exponent. Result 3 i.e. non-integral.

    There is the anomaly that converting input to a floating point variable can give different results (eg integral input looks like a non-integer and vice versa). But, in practice, I've never needed to detect if a floating point variable x holds an integral value - if such a test is needed, it's normally because of a need to understand intent of a user .... hence parsing user input is best.
    Last edited by grumpy; 05-26-2009 at 04:23 AM.
    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.

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> it's not necessary to worry when comparing x and floor(x) if it is necessary to detect that a floating point variable x holds an integral value.

    What about my example? It gives incorrect output.

  13. #13
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Code:
    bool CheckIfWhole(double Input){
       return (Input == (signed long long)Input);
       }

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by abachler View Post
    Code:
    bool CheckIfWhole(double Input){
       return (Input == (signed long long)Input);
       }
    Less likely to be a problem of course, but a double still far exceeds the range of a long long. So 2^100 (which is exactly representable in a double) isn't a whole number with that approach.
    But then you probably already knew that.
    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"

  15. #15
    Registered User
    Join Date
    May 2009
    Posts
    37
    You could also tying doing something like calling frexp, left shifting the result by the exponent part and then testing for 0. I'm not sure if it's any faster though.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fscanf with variable number of entries
    By cfdprogrammer in forum C Programming
    Replies: 5
    Last Post: 04-20-2009, 02:02 AM
  2. HELP!!!!emergency Problem~expert please help
    By unknowppl in forum C++ Programming
    Replies: 9
    Last Post: 08-21-2008, 06:41 PM
  3. HELP!!!!emergency ~expert please help
    By unknowppl in forum C Programming
    Replies: 1
    Last Post: 08-19-2008, 07:35 AM
  4. Using loops for check a roman number input.
    By eryell in forum C++ Programming
    Replies: 9
    Last Post: 04-12-2006, 11:04 AM
  5. How is to check prime number?
    By Unregistered in forum C Programming
    Replies: 7
    Last Post: 10-04-2001, 11:36 PM