今天,我注意到当我将大于最大可能整数的 double 转换为整数时,我得到 -2147483648。同样,当我转换一个小于最小可能整数的 double 时,我也会得到 -2147483648。
是否为所有平台定义了这种行为?
检测这种下溢/溢出的最佳方法是什么?将 min 和 max int 的 if 语句放在强制转换之前是否是最佳解决方案?
最佳答案
将 float 转换为整数时,溢出会导致未定义的行为。来自 C99 规范,6.3.1.4 实数浮点和整数部分:
When a finite value of real floating type is converted to an integer type other than
_Bool
, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.
您必须手动检查范围,但不要使用类似的代码:
// DON'T use code like this!
if (my_double > INT_MAX || my_double < INT_MIN)
printf("Overflow!");
INT_MAX
是一个整数常量,可能没有精确的浮点表示。与 float 进行比较时,它可能会舍入到最接近的更高或最接近的可表示浮点值(这是实现定义的)。例如,对于 64 位整数,INT_MAX
为 2^63 - 1
,通常会四舍五入为 2^63
,因此检查本质上变成 my_double > INT_MAX + 1
。如果 my_double
等于 2^63
,则不会检测到溢出。
例如在 Linux 上使用 gcc 4.9.1,以下程序
#include <math.h>
#include <stdint.h>
#include <stdio.h>
int main() {
double d = pow(2, 63);
int64_t i = INT64_MAX;
printf("%f > %lld is %s\n", d, i, d > i ? "true" : "false");
return 0;
}
打印
9223372036854775808.000000 > 9223372036854775807 is false
如果您事先不知道整数和 double 类型的限制和内部表示,就很难做到这一点。但是,如果您将 double
转换为 int64_t
,例如,您可以使用精确 double 的浮点常量(假设二进制补码和 IEEE double ):
if (!(my_double >= -9223372036854775808.0 // -2^63
&& my_double < 9223372036854775808.0) // 2^63
) {
// Handle overflow.
}
构造 !(A && B)
也能正确处理 NaN。 int
s 的一个可移植、安全但略微不准确的版本是:
if (!(my_double > INT_MIN && my_double < INT_MAX)) {
// Handle overflow.
}
这是出于谨慎的考虑,并且会错误地拒绝等于 INT_MIN
或 INT_MAX
的值。但对于大多数应用程序来说,这应该没问题。
关于c++ - 在 C 中将 double 转换为整数时处理溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/526070/