Check for whole number in template function.

Discussion in 'C++' started by Matthias, Nov 7, 2008.

  1. Matthias

    Matthias Guest

    Dear newsgroup.

    I want to write a template function which accepts either integer or
    floating point numbers.
    If a certain result is not a whole number and if the template
    parameter is an integer, it should return false, but it should work
    normally if the parameter is a float.

    To illustrate this, I attached a minimal example.

    The background:
    I have a variable (in this case "temp") holding the result of some
    calculations and representing a time in milliseconds.
    The output, however, shall be in seconds, and the function should only
    return successfully if the value can be represented in seconds
    (without any rounding).

    The code example below does all that, but I wanted to know if there is
    a better way to do it and if this code works on all systems.

    Is it possible that the "if"-clause is optimized away?
    I compiled it with gcc with the -O3 option and it still works.

    Any comments?

    cheers,
    Matthias

    ======================================

    #include <iostream>

    template <typename T>
    bool minimal(T& output)
    {
    T temp = 500; // change this value!
    if (temp / 1000 * 1000 != temp) return false;
    else output = temp / 1000;
    }

    int main()
    {
    int i;
    if (minimal(i)) std::cout << "int works (" << i << ")!\n";
    float f;
    if (minimal(f)) std::cout << "float works (" << f << ")!\n";
    }
    Matthias, Nov 7, 2008
    #1
    1. Advertising

  2. Matthias

    joseph cook Guest

    On Nov 6, 8:22 pm, Matthias <> wrote:
    > Dear newsgroup.
    >
    > I want to write a template function which accepts either integer or
    > floating point numbers.
    > If a certain result is not a whole number and if the template
    > parameter is an integer, it should return false, but it should work
    > normally if the parameter is a float.
    >
    > To illustrate this, I attached a minimal example.
    >
    > The background:
    > I have a variable (in this case "temp") holding the result of some
    > calculations and representing a time in milliseconds.
    > The output, however, shall be in seconds, and the function should only
    > return successfully if the value can be represented in seconds
    > (without any rounding).
    >
    > The code example below does all that, but I wanted to know if there is
    > a better way to do it and if this code works on all systems.
    >
    > Is it possible that the "if"-clause is optimized away?
    > I compiled it with gcc with the -O3 option and it still works.


    You could look at functions from the limits header like:

    #include <limits>
    if (numeric_limits<T>::is_integer)
    ....

    Joe Cook
    joseph cook, Nov 7, 2008
    #2
    1. Advertising

  3. Matthias

    James Kanze Guest

    On Nov 7, 3:13 am, joseph cook <> wrote:
    > On Nov 6, 8:22 pm, Matthias <> wrote:


    > > I want to write a template function which accepts either
    > > integer or floating point numbers.
    > > If a certain result is not a whole number and if the
    > > template parameter is an integer, it should return false,
    > > but it should work normally if the parameter is a float.


    > > To illustrate this, I attached a minimal example.


    > > The background:
    > > I have a variable (in this case "temp") holding the result
    > > of some calculations and representing a time in
    > > milliseconds. The output, however, shall be in seconds, and
    > > the function should only return successfully if the value
    > > can be represented in seconds (without any rounding).


    > > The code example below does all that, but I wanted to know
    > > if there is a better way to do it and if this code works on
    > > all systems.


    > > Is it possible that the "if"-clause is optimized away? I
    > > compiled it with gcc with the -O3 option and it still works.


    > You could look at functions from the limits header like:


    > #include <limits>
    > if (numeric_limits<T>::is_integer)
    > ....


    Note that numeric_limits<T>::is_integer is NOT a function, and
    that the standard requires it to be usable as an integral
    constant expression. So you can specialize on it, and write
    something like:

    template< bool Is > struct Discriminater {} ;

    template< typename T >
    bool
    functionHelper( T in, Discriminater< true > )
    {
    // handle integer case...
    }

    template< typename T >
    bool
    functionHelper( T in, Discriminater< false > )
    {
    // handle floating point...
    }

    template< typename T >
    bool
    function( T in )
    {
    // ...
    functionHelper(
    in, Discriminater< std::numeric_limits< T >::is_integer
    >() ) ;

    // ...
    }

    (But depending on what he's doing, a simple runtime check might
    be sufficient, and is a lot simpler.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Nov 7, 2008
    #3
  4. Matthias

    Matthias Guest

    Hi again.

    Thanks for the responses!

    On Nov 7, 10:31 am, James Kanze <> wrote:
    > On Nov 7, 3:13 am, joseph  cook <> wrote:
    > > On Nov 6, 8:22 pm, Matthias <> wrote:
    > > > I have a variable (in this case "temp") holding the result
    > > > of some calculations and representing a time in
    > > > milliseconds.  The output, however, shall be in seconds, and
    > > > the function should only return successfully if the value
    > > > can be represented in seconds (without any rounding).
    > > > The code example below does all that, but I wanted to know
    > > > if there is a better way to do it and if this code works on
    > > > all systems.

    [...]
    > > > if (temp / 1000 * 1000 != temp) return false;
    > > > else output = temp / 1000;

    [...]
    > > > Is it possible that the "if"-clause is optimized away?  I
    > > > compiled it with gcc with the -O3 option and it still works.


    > > You could look at functions from the limits header like:
    > > #include <limits>
    > > if (numeric_limits<T>::is_integer)
    > >  ....

    >

    [... code example ...]
    >
    > (But depending on what he's doing, a simple runtime check might
    > be sufficient, and is a lot simpler.)


    Yes, exactly. The is_integer solution might work, but in my case it's
    overkill.
    I would prefer a simple runtime check.

    Let me add some details about the function I'm trying to write:
    In this function an input string is parsed which contains a time. This
    time is normally in seconds, but a suffix can specify if it should be
    hours, minutes, seconds or milliseconds.
    Now if the output type is "int", I only want it to return successfully
    if the result represents the input without loss of information.
    Basically, if the input is "5000ms", the resulting integer should be
    5, but if its "500ms" the function should return an error. The "float"-
    version, however, should simply return 0.5.
    I guess a simple template specialization doesn't work in this case
    because of the dependence on the input string.

    Does the code I suggested in my inital posting work in all cases as
    I'm expecting?
    Or do you know a more suitable runtime check?

    I think I could also rephrase my problem into:
    If a given number having a given type is divided by 1000, does it
    loose any information?

    cheers,
    Matthias
    Matthias, Nov 8, 2008
    #4
  5. Matthias

    Matthias Guest

    Hi Hendrik, hi Group.

    Thanks for the answer, sorry that it took me so long to respond ...

    On 11 Nov., 11:25, Hendrik Schober <> wrote:
    > Matthias wrote:
    > > On Nov 7, 10:31 am, James Kanze <> wrote:
    > > [... code example ...]
    > >> (But depending on what he's doing, a simple runtime check might
    > >> be sufficient, and is a lot simpler.)

    > > Yes, exactly. The is_integer solution might work, but in my case it's
    > > overkill.
    > > I would prefer a simple runtime check.

    >
    >   I'm not sure what "simple runtime check" is supposed to mean.
    >   Does it mean you want a simple check done at run-time or does
    >   it mean run-time checks are (supposed to be) simpler?


    I didn't really think so much about the use of the word "simple", but
    I guess I meant simple in the sense that it's easy to implement and
    easy to read and understand.
    I think in this respect my initial proposal is "simpler", but I still
    don't know if I can use it safely.

    >   There's two dependencies here, from my POV: the one on the
    >   string, which indeed is a run-time one, and the one on the
    >   data type, which is known at compile-time.
    >   I see no problem in checking the type dependency at runtime.
    >   The string parsing has to be done at run-time, but what's to
    >   be done with the result when the data type is an integer
    >   could well be decided at compile-time.


    But everything depends on the input string AND on the data type.
    If the data type is an integer, it should only return successfully if
    the given number is a multiple of 1000.

    Now the question is still: How do I check this reliably?
    And it would be nice if it's still "simple" ...
    Would be nice if that could be done in only very few lines of code.

    Can anyone tell me if my initial proposal is good or bad?
    Here it is again (by the way, I forgot the "return true;" in my
    original posting):

    if (temp / 1000 * 1000 != temp) return false;
    else output = temp / 1000;
    return true;

    cheers,
    Matthias
    Matthias, Nov 13, 2008
    #5
  6. Matthias

    Matthias Guest

    Hello Victor.

    Thanks very much for your response.
    It made me think that maybe templates aren't that good in this
    case ...

    > So, let me get this straight.  When you parse your string, the number
    > that you input can (internally) be of two different types?  How do you
    > make your determination?  Presence of the decimal separator?  So, if the
    > input contains "1.5H", it's floating point, and if it's "1M", it's an
    > integer?  Why?  What if your algorithm always inputs a floating point
    > and if there is a suffix, converts the number to seconds and only then
    > checks if it has a fractional part?  You still can do it, can't you?


    The input string can be either just a number (which would mean
    seconds), or a number with one of the suffixes "h", "min", "s" or
    "ms".
    The number can be positive or negative and it may or may not have a
    decimal point.

    And yes, now I see that I would first have to read a floating point
    value anyway, even if the template type is an integer.

    I just searched for how to check for the fractional part and found the
    modf() function which I didn't know before!
    Are you speaking about this one?

    I think theoretically I could combine this with the is_integer
    solution suggested by James and that would solve my problem.
    But this gets far more complex than what I expected before, so maybe I
    should go the easy way doing it without templates and just implement
    it for one single type, e.g. float.

    > What is the range of times you're hoping to process?  What's the maximum
    > time?  What's the minimum time?  Even 1000H is only 3.6e6 seconds and
    > can be determined to have (or not to have) a fraction if converted to an
    > integer ('unsigned long' should suffice)...


    I was thinking about times from several milliseconds to a few days.

    > I believe you're trying to solve a wrong problem here.


    Yeah, I think you are right.

    The reason why I came up with that problem is that I didn't want to
    decide if I should implement it in float or double.
    For my current use I guess float is sufficient, but I wanted to write
    it in a way that I can use it for other applications in the future.
    So I decided to try it with a template.
    Then I had the problem that the function would also work for integers
    but it would sometimes produce the wrong result ("1600ms" would become
    1 second).

    > Also, have you read the FAQ section 35 (templates)?  Also, did you see
    > my response to your original post?


    Yes, I've read the FAQ section.
    And of course I've read your first response, sorry that I didn't reply
    directly to that, but I wrote in another response that because of the
    dependence on the input string template specialization (alone)
    wouldn't help in my case (If I understood that correctly).

    cheers,
    Matthias
    Matthias, Nov 13, 2008
    #6
  7. Matthias

    Matthias Guest

    Hi Victor.

    Thank you for your very helpful reply!

    I'll implement it with double as you suggested and I will forget about
    all this template Mumbo Jumbo (for now ...).

    Thanks also to the others who responded, I learned quite a lot from
    you!

    cheers,
    Matthias

    On 14 Nov., 14:57, Victor Bazarov <> wrote:
    > Matthias wrote:
    > > Hello Victor.

    >
    > > Thanks very much for your response.
    > > It made me think that maybe templates aren't that good in this
    > > case ...

    >
    > >> So, let me get this straight.  When you parse your string, the number
    > >> that you input can (internally) be of two different types?  How do you
    > >> make your determination?  Presence of the decimal separator?  So, if the
    > >> input contains "1.5H", it's floating point, and if it's "1M", it's an
    > >> integer?  Why?  What if your algorithm always inputs a floating point
    > >> and if there is a suffix, converts the number to seconds and only then
    > >> checks if it has a fractional part?  You still can do it, can't you?

    >
    > > The input string can be either just a number (which would mean
    > > seconds), or a number with one of the suffixes "h", "min", "s" or
    > > "ms".
    > > The number can be positive or negative and it may or may not have a
    > > decimal point.

    >
    > > And yes, now I see that I would first have to read a floating point
    > > value anyway, even if the template type is an integer.

    >
    > > I just searched for how to check for the fractional part and found the
    > > modf() function which I didn't know before!
    > > Are you speaking about this one?

    >
    > Sure.
    >
    > > I think theoretically I could combine this with the is_integer
    > > solution suggested by James and that would solve my problem.

    >
    > You don't need to.  Just use double and be done with it.
    >
    > > But this gets far more complex than what I expected before, so maybe I
    > > should go the easy way doing it without templates and just implement
    > > it for one single type, e.g. float.

    >
    > 'double'.  See below.
    >
    > >> What is the range of times you're hoping to process?  What's the maximum
    > >> time?  What's the minimum time?  Even 1000H is only 3.6e6 seconds and
    > >> can be determined to have (or not to have) a fraction if converted to an
    > >> integer ('unsigned long' should suffice)...

    >
    > > I was thinking about times from several milliseconds to a few days.

    >
    > With the millisecond suffix, how would you specify several days?  There
    > are 86400000 milliseconds in a day, which gives you a range of more than
    > 10 thousand *years* you can safely represent in a *double* (with ~15
    > decimal digits of precision) using the millisecond suffix.  In a *float*
    > with guaranteed 6 digits you can only represent 0.01 day with the
    > millisecond suffix.  That seems a good argument toward using 'double'
    > for your number representation.  And, yes, you can use 'modf'.  If you
    > try to convert to 'unsigned long', you're limited to 49 days of
    > representation with the millisecond suffix, but you will be able to
    > determine if there is fractional part: convert your value to unsigned
    > long, convert the result back to double, and compare the two doubles.
    >
    > > [..]

    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
    Matthias, Nov 14, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. \A_Michigan_User\
    Replies:
    2
    Views:
    882
    \A_Michigan_User\
    Aug 21, 2006
  2. Replies:
    5
    Views:
    317
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=
    Jan 23, 2007
  3. Peng Yu
    Replies:
    3
    Views:
    767
    Thomas J. Gritzan
    Oct 26, 2008
  4. Siew Yee
    Replies:
    1
    Views:
    140
    clintonG
    Aug 13, 2005
  5. babu17
    Replies:
    1
    Views:
    136
Loading...

Share This Page