Ivan Novick said:
However, is it not possible that your double variable could easily
contain some value such as .00000000001 and that !x would return
false.
With 16 bit doubles, .00000000001 is non-zero so converts to true, which
means that the negation of it converts to false. No surprises there.
However, if you run this code:
#include <iostream>
using namespace std;
int main()
{
double x = .00000000001;
while(x)
{
x *= x;
cout << "x is " << x << endl;
if(!x)
cout << "!x evaluates to true\n";
else
cout << "!x evaluates to false\n";
}
return 0;
}
then eventually x becomes zero and !x becomes true because of the
limitations of the representation of a double. This is in spite of the fact
that, in terms of the mathematics of real numbers, squaring a non-zero
number always produces a non-zero result.
An example of the reverse sort of error is the following:
double a = 5.7987982749832, b = 3.27498327984;
double x = (a+b)*(a+b) - (a*a + 2*a*b + b*b);
cout << "x is " << x << endl;
if(!x)
cout << "!x evaluates to true\n";
else
cout << "!x evaluates to false\n";
Here x is zero in terms of the mathematics of real numbers, but (running on
Windows) evaluates to non-zero in terms of the arithmetic of doubles.
I think it is generally unsafe to do exact compares on
floating point variables. Even this if (x == 5)
Floating point representations are in general imprecise and hence
comparisons must be done with caution. Neither "exact compares" nor "inexact
compares" are guaranteed to give the right answer. However, either one may
be appropriate in particular situations.
None of this affects the legality of using a double in a situation that
calls for a bool.