当前位置:  开发笔记 > 编程语言 > 正文

在C中将双精度转换为整数时处理溢出

如何解决《在C中将双精度转换为整数时处理溢出》经验,为你挑选了3个好方法。

今天,我注意到当我将一个大于最大可能整数的double转换为整数时,我得到-2147483648.类似地,当我转换一个小于最小可能整数的double时,我也得到-2147483648.

是否为所有平台定义了此行为?
在/溢出下检测此问题的最佳方法是什么?在演示之前将if语句放入min和max int是最佳解决方案吗?



1> nwellnhof..:

将浮点数转换为整数时,溢出会导致未定义的行为.从C99规范,第6.3.1.4实数浮动和整数:

当实数浮动类型的有限值被转换为除了以外的整数类型时_Bool,小数部分被丢弃(即,该值被截断为零).如果整数部分的值不能用整数类型表示,则行为是未定义的.

您必须手动检查范围,但不要使用如下代码:

// 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 
#include 
#include 

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

如果您事先不知道整数和双精度的限制和内部表示,那么很难做到这一点.但是,如果你转换doubleint64_t,例如,你可以使用精确双倍的浮点常数(假设两个补码和IEEE双精度):

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_MIN或等于的值INT_MAX.但对于大多数应用程序,这应该没问题.



2> qrdl..:

limits.h 具有整数数据类型的最大和最小可能值的常量,您可以在转换之前检查双变量,例如

if (my_double > nextafter(INT_MAX, 0) || my_double < nextafter(INT_MIN, 0))
    printf("Overflow!");
else
    my_int = (int)my_double;

编辑:nextafter()将解决nwellnhof提到的问题


这个答案是错误的,因为不能保证`INT_MIN`和`INT_MAX`具有精确的浮点表示.以64位整数为例,`INT_MAX`为2 ^ 63-1,`(double)INT_MAX`将四舍五入为2 ^ 63,因此如果`my_double`为2 ^ 63,则此检查不会检测到溢出.将检查更改为"my_double> = INT_MAX ||" my_double `nextafter`的唯一问题是,等于`INT_MIN`的`double`将被检测为溢出,尽管它可以转换为`int`.除此之外,它是一个不错的便携式解决方案.

3> Nils Pipenbr..:

回答你的问题:当你抛出范围浮点数时的行为是未定义的或特定于实现的.

从经验谈起:我曾经在MIPS64系统上工作,根本没有实现这些类型的演员表.CPU没有做出确定性的事情,而是抛出了CPU异常.应该模拟转换的异常处理程序,而不对结果做任何事情.

我最终得到了随机整数.猜猜追溯一个错误到这个原因需要多长时间.:-)

如果您不确定该数字是否超出有效范围,您最好自己进行范围检查.

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有