更新:
感谢您提供有用的意见和建议。用你们所说的,这就是我想出的:
#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;
}
我还有另外一个问题。在上面的代码中,当我捕获整数溢出时,我没有返回值 - 它只是return;
。
下面的一条评论建议return -1;
,但考虑到-1仍然是一个有效的整数,这是行不通的,对吗?
我不知道该怎么做,因为我的函数的返回类型是int
。 return;
是否有效或有更好的方法吗?还建议使用exit(1);
,但这会退出整个程序还是只退出函数?
原文:
你的函数应该使用整数运算来确保结果是准确的 还可以检测因超出允许的最大值而导致的任何整数溢出。
我试图在计算二项式系数时捕获整数溢出。虽然这是一个简单的概念,但让我失望的是,这不仅仅是一次性的补充,而是一种不断执行求和的递归算法。
这是功能:
// recursive function to calculate binomial coefficients
int binom(int n, int k){
if(k == 0){ // base case
return 1;
}
else if (n == 0){
return 0;
}
else{
return binom(n - 1, k - 1) + binom(n - 1, k); // recursive call
}
}
根据该逻辑,我假设catch应该在递归调用语句中。类似的东西:
if(binom(n-1, k-1) + binom(n-1,k)) causes overflow, return error, else proceed with binom(n-1, k-1) + binom(n-1,k)
答案 0 :(得分:3)
有符号溢出是未定义的行为,您必须在溢出发生之前检查溢出。
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;
所以对于递归函数:
a = binom(n - 1, k - 1);
b = binom(n - 1, k);
// if no overflow
c = a + b;
return c;
在您的示例中,您还必须检查n
而k
不是== INT_MIN
,否则- 1
操作也会溢出。
答案 1 :(得分:0)
做类似的事情:
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
长。如果不是,请使用更宽的类型)
编辑:如果您不希望exit
出错,则应确定一个值(例如-1
)来表示错误。此外,使用unsigned
代替long
更好(和更正):
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;
答案 2 :(得分:0)
一些建议:
1)您使用的是有符号整数;如果你正在使用严格正数,你应该使用unsigned int或unsigned long long。对于带符号的int,当发生算术溢出时,它将溢出到可能的最大负数
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;
}