将float转换为uint64和uint32的行为很奇怪
Converting float to uint64 and uint32 behaves strangely
当我在c++中将32位浮点数转换为64位无符号整数时,一切都如预期的那样工作。溢出导致设置FE_OVERFLOW标志(cfenv)并返回值0。
std::feclearexcept(FE_ALL_EXCEPT);
float a = ...;
uint64_t b = a;
std::fexcept_t flags;
std::fegetexceptflag(&flags, FE_ALL_EXCEPT);
但是当我将32位浮点数转换为32位无符号整数时,像这样:
std::feclearexcept(FE_ALL_EXCEPT);
float a = ...;
uint32_t b = a;
std::fexcept_t flags;
std::fegetexceptflag(&flags, FE_ALL_EXCEPT);
I的行为与64位转换的方式完全相同,除了上部32位被截断。它等于:
std::feclearexcept(FE_ALL_EXCEPT);
float a = ...;
uint64_t b2 = a;
uint32_t b = b2 & numeric_limits<uint32_t>::max();
std::fexcept_t flags;
std::fegetexceptflag(&flags, FE_ALL_EXCEPT);
因此,仅当指数大于或等于64和时才会发生溢出在指数32和64之间,它返回64位转换的低32位,而不设置溢出。这是非常奇怪的,因为你期望它在指数32处溢出。
这是应该的方式,还是我做错了什么?
编译器为:LLVM version 6.0 (clang-600.0.45.3)(基于LLVM 3.5svn)
从浮点数转换为整数时溢出未定义行为。您不能指望使用单个汇编指令或使用对您希望设置溢出标志的恰好一组值进行溢出的指令来完成此操作。
汇编指令cvttsd2si
,可能已经生成,确实在它溢出时设置标志,但是在转换为32位int类型时可能会生成该指令的64位变体。一个很好的理由是,当截断浮点值为无符号 32位整数时,因为在执行64位有符号指令后,对于导致转换定义的浮点值,目标寄存器的所有32位低位都被正确设置为。cvttsd2si
指令没有无符号的变体。
来自Intel手册:
cvttsd2si -将截断标量双精度FP值转换为有符号整数
…
如果转换结果超过了带符号双字整数的范围限制(在非64位模式下或在REX.W/vax . w =0的64位模式下),则引发浮点无效异常,如果该异常被屏蔽,则返回不确定整数值(80000000H)。
如果转换结果超出了带符号四字整数的范围限制(64位模式和REX.W/VEX. x .)。W = 1),则引发浮点无效异常,如果该异常被屏蔽,则返回不定整数值(80000000_00000000H)。
这篇博文,尽管是C语言的,但对这个主题进行了扩展。
- 没有合适的构造函数可以从"float"转换为"_D3DCOLORVALUE"
- 错误:无法将"float*"转换为"float"
- 有没有一种优雅的方法可以将矢量<复杂<float>>转换为矢量<short>?
- MBED RTOS将Float转换为字符串/字符阵列
- 错误:无法将参数"1"的"float*"转换为"float"
- 有没有快速的方法可以将std::vector<std::vector<float>>转换为std::vector<float2>?
- 将 const float* 转换为 std::array<float, ...>
- 当float转换为int时,此代码中是如何/为什么进行缩小的
- Arduino 无法在初始化时将'float'转换为'const char*'
- C++11自动.从float转换为long
- g++ 在不使用 -Wconvert 的情况下将 double/float 转换为无符号整数时发出警告
- 从 std::vector<std::vector<float>> 转换为 float**
- 在opencv中将垫子转换为矢量<float>和矢量<float>转换为垫子
- 代码一直说:“[错误]无法将参数'1'的'float*'转换为'float'到'void test(flo
- 从'float'转换为'LONG'需要缩小转换范围
- 错误:初始化时无法将'float*'转换为"qreal* {aka double*}"
- Int16_t到float转换的奇怪
- 使用JNI将float*转换为jfloatArray
- 将google::p rotobuf::RepeatedField<float>转换为浮动
- 将float转换为int时的奇怪行为