views:

486

answers:

5

PLease help me out here. The program is supposed to recursively find out the combination of two numbers. nCr = n!/ (r!(n-r)! ). I'm getting this error message when i compile it on GCC.

Here's what the terminal shows:

Enter two numbers: 8 4 Segmentation fault


(Program exited with code:139)

The code is given here:

    #include<stdio.h>

float nCr(float, float, float);

int main()
{

 float a, b, c;
 printf("Enter two numbers: \n");
 scanf("%f%f", &a, &b);
 c = nCr(a, b, a-b);
 printf("\n%.3f", c);
 return 0;
}

float nCr(float n, float r, float p)
{

        if(n<1)
 return (1/(p*r))*(nCr(1, r-1, p-1));

 if(r<1)
 return (n/(p*1))*(nCr(n-1, 1, p-1));

 if(p<1)
 return (n/r)*(nCr(n-1, r-1, 1));

 return ( n/(p*r) )*nCr(n-1, r-1, p-1);
}
A: 

Have you tried debugging the crash? You can use this page as a reference. If you can post information about the crash (stack trace, etc.) that would help both yourself and the SO community in figuring out the problem.

fbrereto
+3  A: 

Since nCr doesn't have any return statement that is not recursive, it will recurse infinitely. Since this will cause the stack to grow infinitely, you get your segmentation fault.

Basically a recursive function should always have at least one possible path through the function which does not recurse. Otherwise you have infinite recursion.

sepp2k
And seeing as 1! = 1, that would be your nonrecursive path. I'd move the factorial calculation to another function and make that the only part of the code with recursion.
peachykeen
thanks for the suggestions. @sepp2k: so the base case i gave was if(n==1 however i'm still getting a segmentation fault. Error code 139.@peachykeen: yes, i'd done that in another program. trying to make a single function for nCr.
AruniRC
A: 

You surely fall into infinite recursion to get this Segmentation Fault. You essentially don't have base case to stop the recursion as sepp2k mentioned.

Petar Minchev
+2  A: 
  1. Why are you using floats? Combinations only deal with integers... Use a formula that doesn't involve floating point arithmetic.
  2. No matter what happens, a recursive call is being made. This means that you will have infinite recursion. This is why the segmentation fault happens. I suggest you read the link I gave you and implement your program using one of the formulas given there. Pay attention to the base cases.
IVlad
thanks, the wikipedia cleared some stuff. using the 'alternate, almost equivalent' computation i rewrote the function. getting numerically incorrect results, working on that.
AruniRC
int comb(int n, int k){ if(k==1) return n; return (n/k)*comb(n-1, k-1);}
AruniRC
You are dividing `n` by `k`, which you shouldn't because you'll either be doing integer division or floating point arithmetic, both of which will lead to incorrect results. User the formula `comb(n, k) = comb(n - 1, k - 1) + comb(n - 1, k) for 0 < k < n and 1 for k = 0 and k = n`.
IVlad
did the floating point arithmetic and the answer came correct - using the values in wikipedia among others. thanks all the same.
AruniRC
Just because you got correct results doesn't mean your results will always come out correct. There is no reason to use floats when dealing with combinations, and I strongly suggest you don't, because it CAN cause problems.
IVlad
Fair enough. Tried out the formula you gave correctly. So i guess both works. Taking (8, 4) as inputs the last program needed 139 calls. the float one took 4. Could you please explain what sort of problems the float would cause because I'm getting whole numbers even in double precision at the end?
AruniRC
A: 

Thanks everyone for the suggestions. It works, it works! :)

    #include<stdio.h>

    float comb(float, float);

int main()
{

    float a, b, c;
    printf("Enter two numbers: \n");
    scanf("%f%f", &a, &b);
    printf("\n%.0f", comb(a, b) );
    return 0;
}

float comb(float n, float k)
{

    if(k==1)
        return n;


    return (n/k)*comb(n-1, k-1); 

}

Please note, though combination works for integers taking int value here will produce error due to the n/k division. Hence the usage float. Without %.0f we'd still get 6 zeroes after the point.

AruniRC