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 26 2920
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.
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)
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.
<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.
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.
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)
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.
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)
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
"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
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.
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
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.
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.
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.
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
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
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
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.
> 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.
"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
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.
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
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
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)
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) This discussion thread is closed Replies have been disabled for this discussion. Similar topics
5 posts
views
Thread by Jukka Lehtonen |
last post: by
|
8 posts
views
Thread by vijay |
last post: by
|
2 posts
views
Thread by Stu Smith |
last post: by
|
3 posts
views
Thread by Andrew Murray |
last post: by
|
14 posts
views
Thread by Joseph Turian |
last post: by
|
1 post
views
Thread by ma740988 |
last post: by
|
12 posts
views
Thread by shaanxxx |
last post: by
|
15 posts
views
Thread by akomiakov |
last post: by
|
17 posts
views
Thread by D'Arcy J.M. Cain |
last post: by
| | | | | | | | | | |