将双精度浮点数安全转换为无符号64位整数

7
在我的平台上,这将打印出9223372036854775808。
double x = 1e19;
std::cout << static_cast<unsigned __int64>(x) << '\n';

我尝试了Boost.NumericConversion,但得到了相同的结果。

x分成两个相等的部分,然后将转换后的两半相加可以得到正确的结果。但我需要一个通用的解决方案来在模板代码中使用。

提前感谢。

编辑:这个问题出现在Visual Studio 2008上,但不是MinGW。将4.0e9强制转换为unsigned long可以正常工作。


相关 - 看起来32位也有类似的问题 :/ - Antti Haapala -- Слава Україні
2个回答

13

看起来gcc可以很好地运行,但在Visual Studio中存在问题。请参见Microsoft的答案

我们的浮点数转整数转换始终是转成有符号整数。在这种情况下,我们使用FIST指令生成了如您所描述的800..00。因此,对于转换为无符号64位整数值而言,不存在定义良好的行为,它们大于最大的64位有符号整数。

因此,您只能将数字转换为有符号的64位整数范围:-9,223,372,036,854,775,808至+9,223,372,036,854,775,807(-2^63〜2^63-1)。


3
您的编译器行为不符合C99标准,它要求正值在可能的情况下应始终正确转换。只允许对负值进行偏差处理。
当将整数类型的值转换为无符号类型时执行的余数运算,在将实浮点类型的值转换为无符号类型时不需要执行。因此,可移植实浮点值的范围为(-1,Utype_MAX + 1)。
对于您的模板代码,您可以测试您的值是否大于static_cast< double >(UINT64_MAX/2)并执行已经在进行的修复工作。如果这仅涉及对常量进行测试,则应在不相关的情况下进行优化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接