float/double equality in template definition without rtti

A

Alexander Block

Hello newsgroup,

let's say I have a function like

template<class Type>
inline bool areEqual(const Type &a, const Type &b)
{
return ( a == b );
}

This could result in a warning, saying the (in)equality of two float or double values is not secure. So I want to treat them as an exception without using RTTI and without defining a seperate function for each possible type. Is that possible ? Are there any ideas of how to realize such kind of functionality ?

Thanks in advance,

Alex
 
R

Rolf Magnus

Alexander said:
Hello newsgroup,

let's say I have a function like

template<class Type>
inline bool areEqual(const Type &a, const Type &b)
{
return ( a == b );
}

This could result in a warning, saying the (in)equality of two float
or double values is not secure. So I want to treat them as an
exception without using RTTI and without defining a seperate function
for each possible type. Is that possible ? Are there any ideas of how
to realize such kind of functionality ?

You can use template specialization. Try this (after the above template
definition):

template<>
inline bool areEqual<float>(const float &a, const float &b)
{
return abs(a - b) < some_epsilon_value; // or whatever you need
}

Btw, if you want this to be inlined, you should consider function
objects instead of regular functions. If you pass your compare-function
as parameter to another function, a pointer to it will be passed and it
will be called through a pointer, which rules out any chance for
inlining.
 
P

Pete Becker

Alexander said:
Hello newsgroup,

let's say I have a function like

template<class Type>
inline bool areEqual(const Type &a, const Type &b)
{
return ( a == b );
}

This could result in a warning, saying the (in)equality of two float or double values is not secure. So I want to treat them as an exception without using RTTI and without defining a seperate function for each possible type. Is that possible ? Are there any ideas of how to realize such kind of functionality ?

Turn of the #$(*&@( warning. Some compiler writer's notion of what might
be a mistake often has very little to do with what's actually correct.
 
R

Rolf Magnus

Pete said:
Turn of the #$(*&@( warning. Some compiler writer's notion of what
might be a mistake often has very little to do with what's actually
correct.

And in this case, the compiler writer's notation of what might be a
mistake is probably right. You should never compare floating point
variables for equality. If you don't know why, then this warning is
especially for programmers like you.
 
A

Andy Venikov

Btw, if you want this to be inlined, you should consider function
objects instead of regular functions. If you pass your compare-function
as parameter to another function, a pointer to it will be passed and it
will be called through a pointer, which rules out any chance for
inlining.

I don't think this statement is correct.
Yeah, sure, if you pass a pointer to this function the compiler
will have to create one global instance of the function, but this
doesn't stop the compiler from using the inlining in other places
where the function is called directly. And using a functor won't
eliminate a function call.

Andy.
 
R

Rolf Magnus

Andy said:
I don't think this statement is correct.
Yeah, sure, if you pass a pointer to this function the compiler
will have to create one global instance of the function, but this
doesn't stop the compiler from using the inlining in other places
where the function is called directly.

That's what I meant. With "rules out any chance for inlining", I
actually meant "rules out any chance for inlining in this place". Where
called directly, the function can indeed be inlined.
And using a functor won't eliminate a function call.

Right, but it can be inlined even when called through a pointer, which a
reglar function can't.
 
P

Pete Becker

Rolf said:
And in this case, the compiler writer's notation of what might be a
mistake is probably right. You should never compare floating point
variables for equality.

Nonsense. There are times when comparing for equality is perfectly
reasonable.
If you don't know why, then this warning is
especially for programmers like you.

I know why, and I also know better than to give advice based on blanket
rules. In particular, if I don't know what someone's requirements are, I
don't advise them to rewrite working code.
 
R

Rolf Magnus

Pete said:
Nonsense. There are times when comparing for equality is perfectly
reasonable.

Maybe, but I'd say those would be very rare.
I know why, and I also know better than to give advice based on
blanket rules.

Then explain in a few words where testing for equality is useful and
where it isn't, and why.
In particular, if I don't know what someone's
requirements are, I don't advise them to rewrite working code.

You don't know whether the OP's code works with the equality test or
not.
 
E

E. Mark Ping

Hello newsgroup,

let's say I have a function like

template<class Type>
inline bool areEqual(const Type &a, const Type &b)
{
return ( a == b );
}

This could result in a warning, saying the (in)equality of two float
or double values is not secure. So I want to treat them as an
exception without using RTTI and without defining a seperate function
for each possible type. Is that possible ? Are there any ideas of how
to realize such kind of functionality ?

When in doubt, listen to what Pete Becker has to say. Then try to
understand it. Then try again. :)

He wrote a series of very good articles about floating-point numbers
that I highly recommend. Find them on his web page:

http://www.petebecker.com/journeymansshop.html

It's 4 articles starting with "Floating-Point Basics".

I also recommend "What Every Computer Scientist Should Know About
Floating-Point Arithmetic". Find it in pdf here:
http://docs-pdf.sun.com/800-7895/800-7895.pdf

or HTML here:
http://docs.sun.com/source/806-3568/ncg_goldberg.html

That being said, why do you want to change this equality test? If two
floats a & b are both computed from a sequence of floating point
operations, you're not guaranteed that they're the same in the
implmentation even if they are the same in theory. However, if b was
assigned to from a, then they will compare the same. Depending on
what you're doing, the == comparison might be the right thing. Or
not.

If you really want to use different cases for float/double
comparisons, you can use the <limits> header and:

std::numeric_limits<Type>::is_integer

which is true for integer types and false for floating point types.
 
C

Carsten Hansen

Rolf Magnus said:
You can use template specialization. Try this (after the above template
definition):

template<>
inline bool areEqual<float>(const float &a, const float &b)
{
return abs(a - b) < some_epsilon_value; // or whatever you need
}

Btw, if you want this to be inlined, you should consider function
objects instead of regular functions. If you pass your compare-function
as parameter to another function, a pointer to it will be passed and it
will be called through a pointer, which rules out any chance for
inlining.

The problem with such a solution is that you can have
a and b areEqual
and
b and c areEqual
but
a and c !areEqual

Moreover, having some_epsilon_value fixed doesn't make sense.

Carsten Hansen
 
A

Alexander Block

Well, thank you for your quick answer. First of all it compiles fine and seems to work. Now I have to read the other postings and pay some more attention to the details and problems.

Alex
 
A

Alexander Block

Dear Pete,

as I saw, the equality of floats and doubles is a common problem not only the notion of some compiler writer's.
What is actually correct in your opinion ?

Alex
 
A

Alexander Block

Perhaps this has been misunderstood. I enabled as much warnings as possible (for me) to see, which parts of my code could cause errors or unexpected behaviour. After reading the warning and some articles in the net, I decided that this is an important warning. So I decided to rewrite my code. To get it working best, I asked the newsgroup for advise.
 
A

Alexander Block

The Links seem to be a good source of information and I will spend some time on reading the articles. Thank you very much.
That means, there doesn't exist "the solution" of the float/double equality problem but the solution depends on the problem to be solved - did I get it right ?
Thank you for the <limits>-hint, but which solution does have a better performance ? I think

template <class Type>
inline bool (const Type &a, const Type &b) {
if ( std::numeric_limits<Type>::is_integer ) {
...
} else {
...
}
}

wouldn't be a good choice, would it ?
 
K

Karl Heinz Buchegger

Alexander said:
Dear Pete,

as I saw, the equality of floats and doubles is a common problem not only the notion of some compiler writer's.
What is actually correct in your opinion ?

The problem with that topic is, that there is no
'one size fits all' solution. Each case must be
thought through independently.

Often a fixed epsilon value works, but also often
it doesn't work. It depends on how many operations
have been done with that float value, the magnitude
of the float values itself and which operations have
been performed. Sometimes a rearrangement of operations
can bring the error back into a range where a fixed
epsilon value can be used, etc.. As said: 'one size
fits all' doesn't work.

"Doing arithmetic with floating-point numbers is like moving
piles of sand. Each time you do it, you loose a little sand
and pick up a little dirt."

Jim Blinn, Dirty Pixels
 
K

Karl Heinz Buchegger

Alexander said:
The Links seem to be a good source of information and I will spend some time on reading the articles. Thank you very much.
That means, there doesn't exist "the solution" of the float/double equality problem

:)

If it existed, the FPU manufacturers would use silicone to
implement it. Since no FPU has such a thing, it doesn't exist. qed.
 
R

Rolf Magnus

Alexander said:
The Links seem to be a good source of information and I will spend
some time on reading the articles. Thank you very much. That means,
there doesn't exist "the solution" of the float/double equality
problem but the solution depends on the problem to be solved - did I
get it right ? Thank you for the <limits>-hint, but which solution
does have a better performance ? I think

template <class Type>
inline bool (const Type &a, const Type &b) {

Your function should still have a name ;-)
if ( std::numeric_limits<Type>::is_integer ) {
...
} else {
...
}
}

wouldn't be a good choice, would it ?

That depends. The if might get optimized away (or it might not), but
is_integer will only check whether your type is an integer or not. If
the funciton is only meant for integers and floating point values, that
may be ok. I'd say the best solution is still to use the template
specialization I presented.
 

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

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top