I am getting SIGFPE Error in the below program and cannot think of a way to remove it.
#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;
}
I am trying to calculate a series which needs factorial but this is giving me SIGFPE error. I use 35
as input.
link to the question: screen shot
35! exceeds the capacity of an unsigned int
on your platform by far.
What happens then is that fact(35)
returns 0, which results in a division by 0 hence the SIGFPE ( f loating p oint e xception).
Consider using the unsigned long long
type, but this won't help for 35 either, because 35! is really huge.
In addition to Jabberwocky answer.
Overflow is not the only reason, yoh have overflow of a 'round' number...
fact(34) returns the amazing result of 0.
If it was a uint64
return value and arg
unsigned long long fact(unsigned long long n)
and you print the result with
printf("%llx",x);
you'll get the result: 445da75b00000000
Cast it to int and you'll get a perfect 0.
It is logical since you have multiply a lot of even numbers and some of the are even power of 2.
In your program, you calculate the binomial coefficient C(n, k) for each possible number of two-task days. The formula is simple:
C(n, k) = n! / (k! * (n - k)!)
but using this formula directly has several problems: The intermediate results, namely the factorials, overflow quickly. Unsigned 32-bit integers can hold factoials up to 12!, unsigned 64-bit integers can hold up to 20!, but after that you will need bignum libraries. The problem statement says that the number of tasks, N, is at most 80. I believe this limit was chosen so that you can do all calculations with uint64_t
from <stdint.h>
.
There are other problems; Raymond Chen outlines them more elegantly than I can. He also proposes a simple way to calculate binomial coefficients, which you can adopt:
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;
}
Oh, and you don't need to distinguish between odd and even N's.
And there's something strange about the challenge: N is the only parameter for each testcase and it can range from 1 to 80, but there can be up to 10,000 test cases. If there are more than 80 cases, N will repeat. Maybe they want you to memoize the results in an array, so that the first time you calculate bthe result, store it and the next time you have to calculate for the same N again, just use the precalculated value. This saves time, and "Time limit exceeded" is a very frequent error in online contests.
You could also try to calculate the first couple of results, say for N from 1 to 10, and print them. Notice a pattern? See, you didn't need the binomial coefficients at all. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.