The below code works on Visual Studio 2008 with and without optimization. But it only works on g++ without optimization (O0).
double round(double v, double digit)
double pow = std::pow(10.0, digit);
double t = v * pow;
//std::cout << "t:" << t << std::endl;
double r = std::floor(t + 0.5);
//std::cout << "r:" << r << std::endl;
return r / pow;
int main(int argc, char *argv)
std::cout << round(4.45, 1) << std::endl;
std::cout << round(4.55, 1) << std::endl;
g++ -O2 round.cpp
Intel x86 processors use 80-bit extended precision internally, whereas
double is normally 64-bit wide. Different optimization levels affect how often floating point values from CPU get saved into memory and thus rounded from 80-bit precision to 64-bit precision.
-ffloat-store gcc option to get the same floating point results with different optimization levels.
Alternatively, use the
long double type, which is normally 80-bit wide on gcc to avoid rounding from 80-bit to 64-bit precision.
man gcc says it all:
-ffloat-store Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or memory. This option prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a "double" is supposed to have. Similarly for the x86 architecture. For most programs, the excess precision does only good, but a few programs rely on the precise definition of IEEE floating point. Use -ffloat-store for such programs, after modifying them to store all pertinent intermediate computations into variables.