By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,820 Members | 1,142 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,820 IT Pros & Developers. It's quick & easy.

float/double equality in template definition without rtti

P: n/a
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
Jul 22 '05 #1
Share this Question
Share on Google+
26 Replies


P: n/a
Alexander Block wrote:
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.

Jul 22 '05 #2

P: n/a
Alexander Block wrote:

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.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #3

P: n/a
Pete Becker wrote:
Alexander Block wrote:

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.


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.

Jul 22 '05 #4

P: n/a
<snip>
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.
Jul 22 '05 #5

P: n/a
Andy Venikov wrote:
<snip>
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.


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.

Jul 22 '05 #6

P: n/a
Rolf Magnus wrote:

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.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #7

P: n/a
Pete Becker wrote:
Rolf Magnus wrote:

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.


Maybe, but I'd say those would be very rare.
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.


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.
Jul 22 '05 #8

P: n/a
Rolf Magnus wrote:

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


He asked about the warning, not about code that didn't work.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #9

P: n/a
In article <c9**********@beech.fernuni-hagen.de>,
Alexander Block <Al*************@fernuni-hagen.de> wrote:
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.
--
Mark Ping
em****@soda.CSUA.Berkeley.EDU
Jul 22 '05 #10

P: n/a

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:c9*************@news.t-online.com...
Alexander Block wrote:
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.


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
Jul 22 '05 #11

P: n/a
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

Rolf Magnus schrieb:
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.

Jul 22 '05 #12

P: n/a
Dear Carsten,

well, and which solution do you suggest to solve the problem ?

Carsten Hansen schrieb:
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

Jul 22 '05 #13

P: n/a
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

Pete Becker schrieb:
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.

Jul 22 '05 #14

P: n/a
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.

Pete Becker schrieb:
He asked about the warning, not about code that didn't work.

Jul 22 '05 #15

P: n/a
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 ?

E. Mark Ping schrieb:
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.

Jul 22 '05 #16

P: n/a
Alexander Block wrote:

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

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #17

P: n/a
Alexander Block wrote:

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.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #18

P: n/a
Karl Heinz Buchegger wrote:

Alexander Block wrote:

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


sorry: silizium
implement it. Since no FPU has such a thing, it doesn't exist. qed.

--
Karl Heinz Buchegger
kb******@gascad.at

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #19

P: n/a
Alexander Block wrote:
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.

Jul 22 '05 #20

P: n/a
> 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.
Sorry for misunderstanding. I interpreted your original comment as if
inlining wouldn't be possible at all for that function.

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.


I don't think I understand you. When you pass a pointer to an object instead
of the pointer to a function, you still have to call operator() through
the object's pointer. It means no inlining is possible for that particular
call. Then how having a functor is better than a pointer to a function?
Andy.
Jul 22 '05 #21

P: n/a

"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message

If it existed, the FPU manufacturers would use silicone to

I like that slip-up. So would the solution be implemented in, say, breast
implants? :-)

sorry: silizium


Since your post is in English (and not German), wouldn't the correct term be
"silicon"? I doubt many English-speaking folk know the term "silizium".
-Howard
Jul 22 '05 #22

P: n/a
Andy Venikov wrote:
> 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.


I don't think I understand you. When you pass a pointer to an object
instead of the pointer to a function, you still have to call
operator() through the object's pointer. It means no inlining is
possible for that particular call.


It doesn't call the function through the pointer to the object. It just
calls the function using a regular function call (or inline) with the
pointer to the object as a hidden parameter.
However, this is only true for non-virtual functions. Virtual functions
would usually need to be called through a vtable pointer.

Jul 22 '05 #23

P: n/a
In article <2h************@uni-berlin.de>,
Alexander Block <Al*************@fernuni-hagen.de> wrote:
The Links seem to be a good source of information and I will spend
some time on reading the articles. Thank you very much.
You're welcome. And oh:

A: Because it makes the message harder to read.Q: Why shouldn't I top post? 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 ?


Yes.

(Side note: In my opinion this is a defective compiler. This kind of
warning may be useful in a Lint-style tool, but IMO doesn't belong in
a compiler.)

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

Our compiler at least optimized the "if" statement away. If that
isn't the case for you, template specialization may be a solution.

Also, you may be able to overload a template function using
Int2Type< std::numeric_limits<Type>::is_integer >.

I highly recommend reading Andrei Alexandrescu's "Modern C++ Design"
if you go down this path.

If the warning is specious, I recommend disabling it. Otherwise,
you're going to spend a lot of effort on an unnecessary adventure.
--
Mark Ping
em****@soda.CSUA.Berkeley.EDU
Jul 22 '05 #24

P: n/a
In article <c9*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
Pete Becker wrote:

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


Maybe, but I'd say those would be very rare.


It depends on the problem domain. It can be very common in the work I
do. In particular, the following case:

float a,b;

a = SomeGnarlyCalcultion();
b = a;
....
....

if (b == a)
{
}

is a situation in which (b == a) must be true IIRC.
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.


Then explain in a few words where testing for equality is useful and
where it isn't, and why.


He's explained in detail in several articles. You may have noticed
that I referenced some of his articles elsewhere. I suggest you read
them before quizzing him on his knowledge of FP.
--
Mark Ping
em****@soda.CSUA.Berkeley.EDU
Jul 22 '05 #25

P: n/a
Andy Venikov wrote:

I don't think I understand you. When you pass a pointer to an object instead
of the pointer to a function, you still have to call operator() through
the object's pointer.
Right.
It means no inlining is possible for that particular
call.


If operator() isn't virtual it doesn't matter whether the call is
through a pointer, a reference, or a named object. The compiler sees the
full code, and can inline it.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #26

P: n/a
Alexander Block wrote:

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 ?


Absolutely right.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #27

This discussion thread is closed

Replies have been disabled for this discussion.