在递归函数[C]中捕获整数溢出
更新: 感谢您的宝贵意见和建议。根据你们所说的,这就是我想到的:在递归函数[C]中捕获整数溢出,c,recursion,integer,overflow,C,Recursion,Integer,Overflow,更新: 感谢您的宝贵意见和建议。根据你们所说的,这就是我想到的: #include <limits.h> ... else { int a = binom(n - 1, k - 1); int b = binom(n - 1, k); if(a > 0) { if (b > INT_MAX - a) { // case 1: integer overflow printf(
#include <limits.h>
...
else {
int a = binom(n - 1, k - 1);
int b = binom(n - 1, k);
if(a > 0) {
if (b > INT_MAX - a) { // case 1: integer overflow
printf("int overflow\n");
return;
}
}
else if (b < INT_MIN - a) { // case 2: integer overflow
printf("int overflow\n");
return;
}
int c = a + b;
return c;
}
在这种逻辑下,我假设捕获应该在递归调用语句中。比如:
如果(binom(n-1,k-1)+binom(n-1,k))导致溢出,返回错误,否则继续执行binom(n-1,k-1)+binom(n-1,k)
执行以下操作:
long res=(long)binom(n - 1, k - 1) + binom(n - 1, k);
if (res>INT_MAX) {
printf("int overflow\n");
exit(1);
}
return (int)res;
(假设系统中的long
比int
长。如果不是这样,请使用更宽的类型)
编辑:如果您不想在出现错误时退出,
,则应确定一个值(例如,-1
),以表示错误。此外,使用无符号
比使用长
更好(更准确):
int a=binom(n - 1, k - 1),b=binom(n - 1, k);
if (a<0 || b<0 || (unsigned)a+(unsigned)b>INT_MAX) return -1;
return a+b;
inta=binom(n-1,k-1),b=binom(n-1,k);
如果(aSigned overflow)是未定义的行为,则必须在溢出发生之前检查溢出
int a, b;
int c;
...
/* Compute a + b and store the result in c */
if (a > 0) {
if (b > INT_MAX - a) {
// a + b overflows (i.e., would be > INT_MAX)
}
} else if (b < INT_MIN - a) {
// a + b overflows (i.e., would be < INT_MIN)
}
c = a + b;
在您的示例中,还必须检查n
和k
不是==INT\u MIN
,否则-1
操作也将溢出。一些建议:
1) 您使用的是有符号整数;如果使用的是严格的正数,则可能应该使用无符号int或无符号long。对于有符号整数,当发生算术溢出时,它将溢出到可能的最大负数
2) 编译器将沿INT_MAX行定义一个预处理器符号;你或许可以好好利用它,例如:
#inlcude <stdtypes.h>
uint32_t binom( uint32_t n, uint32_t k ){
// (...)
} else {
int32_t A = binom( n-1, k-1 )
, B = binom( n-1, k );
if( (double)A + (double)B > INT_MAX ){
// error condition
} else {
retval = A+B;
}
}
return retval;
}
#包括
uint32\u t binom(uint32\u t n,uint32\u t k){
// (...)
}否则{
int32_t A=binom(n-1,k-1)
,B=binom(n-1,k);
如果((双)A+(双)B>INT_MAX){
//错误条件
}否则{
retval=A+B;
}
}
返回返回;
}
另一个递归调用也应该有类型转换(long)binom(n-1,k)
这假设sizeof(long)>sizeof(int)
,但这不能保证为真。@fredrarson你是对的。补充说明@noMad,long
和int
的总和是long
@aselr不一定有更广泛的本机类型可用(想想那些int
和long
都是64位的系统)。@从这里我没有想到这一点。。。希望现在我是正确的:)非常感谢——这是我使用的实现。我还有一个问题。如果出现溢出,我将如何中断函数?如果我返回一个像-1这样的整数标志(如下所示),由于这是递归的,它将继续求和,因为-1是一个数字。
a = binom(n - 1, k - 1);
b = binom(n - 1, k);
// if no overflow
c = a + b;
return c;
#inlcude <stdtypes.h>
uint32_t binom( uint32_t n, uint32_t k ){
// (...)
} else {
int32_t A = binom( n-1, k-1 )
, B = binom( n-1, k );
if( (double)A + (double)B > INT_MAX ){
// error condition
} else {
retval = A+B;
}
}
return retval;
}