Secure conversion from binary and unsigned 64-bit integer

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 result.

Dividing x into 2 equal parts, then adding the converted halves will give the correct result. But I need a general solution for use in template code.

Thanks in advance.

EDIT: This issue occurs in Visual Studio 2008, but not in MinGW. Casting 4.0e9 in unsigned long works fine.

+6
c ++ c
source share
2 answers

It seems to work well with gcc, but in Visual Studio this is problematic. See Microsoft's answer on this issue:

Our floating point to integer conversions are always performed with a signed integer. In this particular, we use the FIST statement, which generates 800..00, as you described. Therefore, there is no specific behavior for converting to unsigned 64-bit integer values ​​that are larger than the largest 64-bit subscription integer.

Thus, you can only convert numbers to a signed 64-bit integer range: -9,223,372,036,854,775,808 - +9,223,372,036,854,775,807 (-2 ^ 63 ~ 2 ^ 63-1).

+10
source share

The behavior of your compiler is not consistent with C99, it requires that positive values ​​are always correctly converted, if possible. This allows you to only deviate from negative values.

The remaining operation when the value of an integer type converted to an unsigned type is not required is performed when the value of a real floating type is converted to an unsigned type. Thus, the range of portable real floating values ​​is (-1, Utype_MAX + 1).

For the template code, you can simply check if your value exceeds the value of static_cast< double >(UINT64_MAX/2) and carry out your repair work. If it concerns testing only for constants, it should be optimized where it does not matter.

+1
source share

All Articles