When I run the following code in VC++ 2013 (32-bit, no optimizations):
#include
#include
#include
double mulpow
Hypothesis: It is a bug. The compiler converts double
to unsigned long long
correctly but converts extended-precision floating-point (possibly long double
) to unsigned long long
incorrectly. Details:
double x = std::floor(9710908999.0089989 * 1.0E9);
This computes the value on the right-hand side and stores it in x
. The value on the right-hand side might be computed with extended precision, but it is, as the rules of C++ require, converted to double
when stored in x
. The exact mathematical value would be 9710908999008998870, but rounding it to the double
format produces 9710908999008999424.
unsigned long long y1 = x;
This converts the double
value in x
to unsigned long long
, producing the expected 9710908999008999424.
unsigned long long y2 = std::floor(9710908999.0089989 * 1.0E9);
This computes the value on the right-hand side using extended precision, producing 9710908999008998870. When the extended-precision value is converted to unsigned long long
, there is a bug, producing 263 (9223372036854775808). This value is likely the “out of range” error value produced by an instruction that converts the extended-precision format to a 64-bit integer. The compiler has used an incorrect instruction sequence to convert its extended-precision format to an unsigned long long
.