Check for whole number in template function.

M

Matthias

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";
}
 
J

joseph cook

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
 
J

James Kanze

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 said:
// ...
}

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

Matthias

Hi again.

Thanks for the responses!

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
 
M

Matthias

Hi Hendrik, hi Group.

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

  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
 
M

Matthias

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
 
M

Matthias

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

Matthias said:
Hello Victor.
Thanks very much for your response.
It made me think that maybe templates aren't that good in this
case ...
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.
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top