Consider two following pieces of code - the only difference between them is a single cout which prints the value eps:
http://ideone.com/0bEeHz - here the program enters and infinite loop since after the cout eps changes value to 0
#include <iostream>
int main()
{
double tmp = 1.;
double eps;
while(tmp != 0) {
eps = tmp;
tmp /= 2.;
}
if(eps == 0) {
std::cout << "(1)eps is zero!\n";
}
std::cout << "eps before: " << eps;
if(eps == 0) {
std::cout << "(2)eps is zero!\n";
}
while(eps < 1.) {
tmp = eps;
eps *= 2.;
if(tmp == eps) {
printf("wtf?\n");
}
}
std::cout << "eps after: " << eps;
}
http://ideone.com/pI4d30 - here I've commented out the cout.
#include <iostream>
int main()
{
double tmp = 1.;
double eps;
while(tmp != 0) {
eps = tmp;
tmp /= 2.;
}
if(eps == 0) {
std::cout << "(1)eps is zero!\n";
}
//std::cout << "eps before: " << eps;
if(eps == 0) {
std::cout << "(2)eps is zero!\n";
}
while(eps < 1.) {
tmp = eps;
eps *= 2.;
if(tmp == eps) {
printf("wtf?\n");
}
}
std::cout << "eps after: " << eps;
}
Hence, one single cout changes program logic dramatically and very surprisingly. Why is that?
I think it's a case of Section 5 (Expressions), paragraph 11
The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby.
at work, cf. this variation of the original code.
while(tmp != 0) {
eps = tmp;
tmp /= 2.;
}
Calculations and comparisons performed at extended precision. The loop runs until eps
is the smallest positive extended value (probably the 80-bit x87 extended type).
if(eps == 0) {
std::cout << "(1)eps is zero!\n";
}
Still at extended precision, eps != 0
std::cout << "eps before: " << eps;
For the conversion to a string to print, eps
is stored and converted to double
precision, resulting in 0.
if(eps == 0) {
std::cout << "(2)eps is zero!\n";
}
Yes, now it is.