当我们将 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
进行讨论。)
大 int
到 float
有丢失精度的风险,因为 float
没有完全编码所有 int
。使用 OP int num = 2147483647; (float)num
,2147483647 被转换为附近 2 个中的 1 个 float
。使用四舍五入模式,float
: 结果肯定是 2147483648.0.
float
到 int
截断任何分数。从无穷大和非数字转换会带来加法问题。
当浮点值不在 -2,147,483,648.9999... 2,147,483,647.9999... 范围内时,float
到 int
存在实现定义行为的风险。 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);
}
可能需要其他测试来确定舍入或截断。
- 代码
#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
进行讨论。)
大 int
到 float
有丢失精度的风险,因为 float
没有完全编码所有 int
。使用 OP int num = 2147483647; (float)num
,2147483647 被转换为附近 2 个中的 1 个 float
。使用四舍五入模式,float
: 结果肯定是 2147483648.0.
float
到 int
截断任何分数。从无穷大和非数字转换会带来加法问题。
float
到 int
存在实现定义行为的风险。 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);
}
可能需要其他测试来确定舍入或截断。