c++ - 在 C 中将 double 转换为整数时处理溢出

标签 c++ c casting floating-point

今天,我注意到当我将大于最大可能整数的 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_MAX2^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。 ints 的一个可移植、安全但略微不准确的版本是:

if (!(my_double > INT_MIN && my_double < INT_MAX)) {
    // Handle overflow.
}

这是出于谨慎的考虑,并且会错误地拒绝等于 INT_MININT_MAX 的值。但对于大多数应用程序来说,这应该没问题。

关于c++ - 在 C 中将 double 转换为整数时处理溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/526070/

相关文章:

c++ - `static_cast<bool>(x)` 和 `x != 0.0` 之间有区别吗?

java - Java 中未经检查的强制转换警告

c++ - QTableWidget 中的 SelectedRows 列表

c - 如何使用 WinAPI 识别光驱中的光盘类型?

c++ - 配置 KDevelop

c - 多维c数组的问题

c# - 在 C# 中,将接口(interface)列表转换为对象列表的推荐方法是什么?

c++ - 为什么没有像 pthread_mutex_t & std::mutex 那样的 std::等价于 pthread_spinlock_t?

c++ - 如果可能,在编译时检查一个值

C++:在 Vista 上获取网络适配器的 MAC 地址?