当我们将 int 转换为 float 为 int 时,在 c 中适应 int 溢出的正确方法

Proper way to fit int overflow in c, when we cast int to float to int

#include <iostream>

int main() {
    int  num = 2147483647;
    std::cout << (int)(float)num << std::endl; 

    return 0;
}
./main
-2147483648
-2147483648

我知道 float 到 int 的转换是安全的,但 int 到 float 的转换是不安全的。我也知道真正的浮点数是无法准确表达的。即使没有超过 int 的最大值(inf 除外),看到溢出也是非常危险的。

无论传入什么任意数字,我都希望在将 int 转换为 float 或将 float 转换为 int 时是安全的。

哪种处理方式最好?另外,我还应该考虑哪些其他例外情况?


上面的问题不清楚,不符合Whosebug的问题,所以我会专门修复它。

2147483647 等普通类别的号码也溢出。我应该处理什么范围?

I know that a float to int conversion is safe, but an int to float conversion is not.

每次转换都有问题。

(假设32位int和32位float进行讨论。)

intfloat 有丢失精度的风险,因为 float 没有完全编码所有 int。使用 OP int num = 2147483647; (float)num,2147483647 被转换为附近 2 个中的 1 个 float。使用四舍五入模式,float: 结果肯定是 2147483648.0.

floatint 截断任何分数。从无穷大和非数字转换会带来加法问题。

当浮点值不在 -2,147,483,648.9999... 2,147,483,647.9999... 范围内时,

floatint 存在实现定义行为的风险。 OP 的 int num = 2147483647; (int)(float)num 试图将超出范围的 2147483648.0 转换为 int 就是这种情况。在 OP 的情况下,该值显然环绕(减去 232)以 -2147483648.

结尾

Which way is best to handle it? Also, what other exceptions should I consider?

int 转换为 float,预计大 int 的四舍五入。

float 转换为 int,预计会出现截断并可能测试值是否在范围内。

使用 2 的补码整数编码:防止超出范围转换的测试。

#define FLT_INT_MAX_PLUS1 ((INT_MAX/2 + 1)*2.0f)

// return true when OK to convert 
bool float_to_int_test(float x) {
  return (x < FLT_INT_MAX_PLUS1) && (x - INT_MIN > -1.0f);
}

可能需要其他测试来确定舍入或截断。