Reputation: 903
i'm working on a project and to finish it i need to do some comparison with double, float ... the problem is when i compare two double which are respectively the biggest value for a double and the biggest value for a double + 1, the comparison fail ... i do
if (std::max(d_max + 1.1, (d_max)) == d_max)
std::cout << "bad" << std::endl;
the answer of the function max is d_max and "bad" is displayed ... is anyone having an idea or a solution to get a good precision with my comparison ? i checked on google but i found out more explanations than real solution to my problem ... thanks so much !
Upvotes: 0
Views: 935
Reputation: 110658
All objects in C++ have a type. The type of d_max
is double
. The type of d_max + 1.1
is still double. If d_max
is the maximum value for a double
, then d_max + 1.1
is not representable and the closest representable value will be used, which is d_max
(however, if you add a significantly larger value, the closest representable value is considered to be positive infinity). So your std::max
call is equivalent to:
std::max(d_max, d_max)
To demonstrate:
double d_max = std::numeric_limits<double>::max();
bool b = (d_max == (d_max + 1.1));
std::cout << std::boolalpha << b << std::endl;
This gives true
as output.
In response to your comment, I assume you are doing something like this:
double d_max = std::numeric_limits<double>::max();
long double ld = d_max + 1;
std::cout << (d_max == ld) << std::endl;
And strangely you find that apparently d_max
and ld
are equal. Why? Well d_max
is a double
. When you do d_max + 1
, the result of the operation is also a double
- the value of d_max + 1
can't be represented in a double
though, as described before, so the closest representable value (d_max
) is chosen. This value is then assigned to ld
.
Note that this isn't likely to be fixed by just making sure the operator results in a long double
(perhaps with d_max + 1.0L
). At such huge numbers (around 10^308
with an IEEE 754 representation), adding 1 will not move you along to the next representable value in a long double
. With my implementation, I have to add 10289 (that's 1 followed by 289 zeros) to actually cause a change in value:
double d_max = std::numeric_limits<double>::max();
long double ld = d_max + 1E289L;
std::cout << (d_max == ld) << std::endl;
Also, there is no guarantee that long double
has more precision than double
. The only guarantee is that it doesn't have less precision.
Upvotes: 7
Reputation: 120711
Let's pretend doubles are represented as decimal floating-point numbers, scientific notation. Then, d_max
would be something like
9.999999999999999999 ⋅ 10⁹⁹
Now let's add 1.1
to that:
9.999999999999999999 ⋅ 10⁹⁹ + 1.1
= 999999999999999999900000000...000 + 1.1
= 999999999999999999900000000...001.1
round that to 20, or even 40 significant figures (which you have to as those types, even long double, have only finite information capacity) and you get...? well, d_max
again.
int main() {
long double d_max = std::numeric_limits<double>::max();
if(d_max == d_max - 1.1)
std::cout << " d_max = " << d_max
<< "\n== d_max - 1.1 = " << d_max + 1.1 << std::endl;
return 0;
}
outputs
d_max = 1.79769e+308
== d_max - 1.1 = 1.79769e+308
i.e. this really hasn't anything to do with d_max
being the largest value available, but with it being so much larger than what you add to it.
Upvotes: 1