当一个整数转换为浮点时,而该值不能直接用目的类型表示时,通常选择最近的值(IEEE-754)。
如果整数值不能直接由浮点类型表示,我想将整数转换为浮点,并向零舍入。
示例:
int i = 2147483647;
float nearest = static_cast<float>(i); // 2147483648 (likely)
float towards_zero = convert(i); // 2147483520
您可以使用std::nextafter
。
int i = 2147483647;
float nearest = static_cast<float>(i); // 2147483648 (likely)
float towards_zero = std::nextafter(nearest, 0.f); // 2147483520
但是您必须检查static_cast
是否正确,如果正确,nextafter
将向0迈进一步,这可能是您不希望看到的。
您的convert
函数可能如下所示:
float convert(int x){
if(std::abs(long(static_cast<float>(x))) <= std::abs(long(x)))
return static_cast<float>(x);
return std::nextafter(static_cast<float>(x), 0.f);
}
当static_cast
超过可能的值时,sizeof(int)==sizeof(long)
或甚至sizeof(int)==sizeof(longlong)
在本例中long(...)
可能表现为未定义。 根据编译器的不同,它可能在这种情况下仍然有效。
在整数可用浮点数表示之前,可以丢弃最低有效位
float convert(int x){
for( int i = 2; static_cast<int>(static_cast<float>(x)) != x; i<<=1){
x = (x / i) * i;
}
return static_cast<float>(x);
}
一个简单的解决方案是使用更高精度的浮点进行比较。 只要高精度浮点能准确表示所有整数,我们就能准确比较float
结果是否更大。
对于32位整数,double
应该足够了,对于大多数系统上的64位整数,long double
也足够了,但最好进行验证。
float convert(int x) {
static_assert(std::numeric_limits<double>::digits
>= sizeof(int) * CHAR_BIT);
float f = x;
double d = x;
return std::abs(f) > std::abs(d)
? std::nextafter(f, 0.f)
: f;
}