On my platform this prints 9223372036854775808.
double x = 1e19;
std::cout << static_cast<unsigned __int64>(x) << '\n';
I tried Boost.NumericConversion, but got the same re开发者_JAVA技巧sult.
Splitting x into 2 equal part, then adding together converted halves give the correct result. But I need a generic solution to use in a template code.
Thank you in advance.
EDIT: This problem shows up on Visual Studio 2008, but not MinGW. Casting 4.0e9 into unsigned long works fine.
Seems like it works well with gcc, but it is problematic in Visual Studio. See Microsoft's answer regarding this issue:
Our floating-point to integer conversions are always done to a signed integer. In this particular case we use FIST instruction which generates 800..00 as you described. Therefore, there is no defined behavior for converting to unsigned 64-bit integer values which are larger than largest 64-bit signed integer.
So you can only convert the numbers in the signed 64-bit integer range: −9,223,372,036,854,775,808 to +9,223,372,036,854,775,807 (-2^63~2^63-1).
The behavior of your compiler is not conforming to C99, it requires that positive values should always be converted correctly if possible. It only allows to deviate from that for negative values.
The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type. Thus, the range of portable real floating values is (−1, Utype_MAX+1).
For you template code, you might just test if your value is greater than static_cast< double >(UINT64_MAX/2)
and do the repair work that you are already doing. If this only concerns testing for constants, this should be optimized out where it is not relevant.
精彩评论