Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Check for whole number in template function. (http://www.velocityreviews.com/forums/t643358-check-for-whole-number-in-template-function.html)

Matthias 11-07-2008 01:22 AM

Check for whole number in template function.
 
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";
}

joseph cook 11-07-2008 02:13 AM

Re: Check for whole number in template function.
 
On Nov 6, 8:22*pm, Matthias <Matthias.Ge...@gmail.com> 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


James Kanze 11-07-2008 09:31 AM

Re: Check for whole number in template function.
 
On Nov 7, 3:13 am, joseph cook <joec...@gmail.com> wrote:
> On Nov 6, 8:22 pm, Matthias <Matthias.Ge...@gmail.com> 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:james.kanze@gmail.com
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

Matthias 11-08-2008 05:50 PM

Re: Check for whole number in template function.
 
Hi again.

Thanks for the responses!

On Nov 7, 10:31*am, James Kanze <james.ka...@gmail.com> wrote:
> On Nov 7, 3:13 am, joseph *cook <joec...@gmail.com> wrote:
> > On Nov 6, 8:22 pm, Matthias <Matthias.Ge...@gmail.com> 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 11-13-2008 03:45 PM

Re: Check for whole number in template function.
 
Hi Hendrik, hi Group.

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

On 11 Nov., 11:25, Hendrik Schober <spamt...@gmx.de> wrote:
> Matthias wrote:
> > On Nov 7, 10:31 am, James Kanze <james.ka...@gmail.com> 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 11-13-2008 10:45 PM

Re: Check for whole number in template function.
 
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 11-14-2008 06:01 PM

Re: Check for whole number in template function.
 
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 <v.Abaza...@comAcast.net> 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




All times are GMT. The time now is 07:38 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.