我在下面的程序中遇到SIGFPE错误,无法想到将其删除的方法。
#include <stdio.h>
unsigned int fact(unsigned long int n)
{
if (n <= 0)
return 1;
return n*fact(n-1);
}
int main(){
int t,r,x,y,z,sum=0,n;
scanf("%d",&t);
for(int l=0; l<t; l++){
scanf("%d",&n );
if(n%2==0){
for(int j=n,i=0,k=n; k>=0&&j>0;i++, j++,k-=2){
x=fact(n-i);
y=fact(k);
z=fact(n-k-i);
sum=sum+ (x)/(y*z);
}
printf("%d\n",sum );
}
if(n%2!=0){
for(int j=n,i=0,k=n; k>=1&&j>0;i++, j++,k-=2){
x=fact(n-i);
y=fact(k);
z=fact(n-k-i);
sum=sum+ (x)/(y*z);
}
printf("%d\n",sum);
}
sum=0;
}
return 0;
}
我正在尝试计算一个需要阶乘的级数,但这给了我SIGFPE错误。我使用35
作为输入。
链接到问题:screen shot
答案 0 :(得分:4)
35!远远超过了您平台上unsigned int
的容量。
然后发生的情况是fact(35)
返回0,结果除以0,因此SIGFPE( f 浮动 p oint e < / strong>欺骗”。
考虑使用unsigned long long
类型,但这对35也不起作用,因为35!真的很大。
答案 1 :(得分:0)
除了Jabberwocky答案。
溢出不是唯一的原因,哦,有一个“舍入”数字溢出...
fact(34)返回惊人的结果0。
如果它是uint64
的返回值和arg
unsigned long long fact(unsigned long long n)
,然后使用
打印结果printf("%llx",x);
您将得到结果:445da75b00000000
将其转换为int即可得到完美的0。
这是合乎逻辑的,因为您已经将许多偶数相乘,并且有些乘数是2的偶数次幂。
答案 2 :(得分:0)
在您的程序中,您为每个可能的两个任务天数计算二项式系数C(n,k)。公式很简单:
C(n, k) = n! / (k! * (n - k)!)
,但是直接使用该公式有几个问题:中间结果,即阶乘,迅速溢出。无符号的32位整数最多可容纳12!个事实,无符号的64位整数最多可容纳20!个,但是此后,您将需要bignum库。问题陈述指出,任务数N最多为80。我相信选择了此限制,以便您可以使用uint64_t
中的<stdint.h>
进行所有计算。
还有其他问题; Raymond Chen比我更优雅地概述了它们。他还提出了一种计算二项式系数的简单方法,您可以采用:
uint64_t binom(uint64_t n, uint64_t k)
{
uint64_t c = 1u;
uint64_t i;
for (i = 0; i < k; i++) {
c *= n - i;
c /= i + 1;
}
return c;
}
哦,您不需要区分N的奇数和偶数。
这个挑战有一个奇怪的地方:N是每个测试用例的唯一参数,它的范围可以从1到80,但最多可以有10,000个测试用例。如果超过80个,N将重复。也许他们希望您将结果记忆在一个数组中,以便第一次计算该结果时将其存储起来,而下次您必须再次针对相同的N计算时,只需使用预先计算的值即可。这样可以节省时间,并且“超过时间限制”是在线竞赛中非常常见的错误。
您还可以尝试计算前几个结果,例如从1到10的N值,然后打印出来。注意到模式吗?看,您根本不需要二项式系数。 :)