将大 int 转换为浮点数,而不舍入 c++

Convert large int to float without rounding c++

本文关键字:不舍 舍入 c++ 浮点数 int 转换 将大      更新时间:2023-10-16

有没有一种快速干净的方法可以将int32_t(或更大(转换为浮点数中不大于int32_t中存储的原始值的最大可表示值?

根据IEEE754标准(在维基百科 https://en.wikipedia.org/wiki/Single-precision_floating-point_format 上只读(,大整数的转换是通过四舍五入到最接近的 2 次方的倍数来完成的。哪个幂取决于该值的大小。

但是,我想知道,是否可以将这种转换为"最大浮点数而不是更大",并以干净的方式进行,而无需复杂的构造,理想情况下是通过设置一些标志或使用一些内置指令?

编辑:我有一个值x_int存储在int32_t或int64_t中,我想将其转换为浮点值x_float,以便对于这些值(数学上,而不是在编程滞后(

x_int>=x_float

总是正确的。int32_t可能的解决方法是使用双精度,但我不确定int64_t。

行为可能取决于有效的编译器选项。例如,在 msvc 中/fp:fast为了速度而牺牲了正确性。如果这不是您想要的,请指定/fp:strict/fp:precise(默认值(。在Clang上,-menable-unsafe-fp-math做了类似的事情。

浮点舍入模式由fesetround控制。

  • http://www.cplusplus.com/reference/cfenv/fesetround/
使用fegetround

检索舍入模式,以便以后恢复它,接下来使用fesetround设置所需的舍入模式(在您的情况下FE_TOWARDZERO如果您的意思是幅度最小,否则FE_DOWNWARD(,然后将其转换为float。最后恢复舍入模式。

inline float cast_with_mode(int32_t value, int mode){
int prevmode = fegetround();
if(prevmode == mode) return (float)value; // may be faster without this
fesetround(mode);
float result = (float)value;
fesetround(prevmode);
return result;
}

性能方面,将prevmodemode进行比较可能会更好,也可能不会更好。如果它已经正确,则无需设置或还原它。我不知道比较是比设置/恢复更快还是更慢。

示例输出(在 Clang 和 G++ 上相同(:

Mode           Value       Value          ResultBits   Result Value
FE_TOWARDZERO: 2147483520  0x7fffff80  => 4effffff     2147483520.000000
FE_UPWARD:     2147483520  0x7fffff80  => 4effffff     2147483520.000000
FE_TOWARDZERO: 2147483584  0x7fffffc0  => 4effffff     2147483520.000000
FE_UPWARD:     2147483584  0x7fffffc0  => 4f000000     2147483648.000000