I am trying to compute n! % m using recursion in C. This is the code I am using
#include<stdio.h>
#define m 1000000007
long long int fact(long long int n) {
if(n == 1)
return (1);
long long int n2 = (long long int)(fact(n-1));
long long int k = (n*n2)%m;
return k;
}
int main() {
printf("%lld",fact(1000000));
}
This program gives SEGMENTATION FAULT , but if I replace the fact function with an iterative approach then program prints correct answer.The iterative fact function is
long long int fact(long long int n){
long long int k =1;
long long int i;
for(i = n;i>1;i--)
k = (k*i)%m;
return k;
}
So why the iterative approach works but the recursive approach is failing?
try gdb, but likely its because you are reaching your max recursion depth, in other words running out of "memory" either literally or based on current rule sets for your os.
If your C compiler optimizes tail calls you can rewrite your recursive function to a tail recursive one:
long long int fact_aux(long long int n, long long int acc) {
if(n <= 1)
return acc;
return fact_aux(n-1, (n * acc)%m);
}
long long int fact(long long int n) {
return fact_aux(n, 1);
}
Note that the C standard doesn't require TCO so you have no guarantee this will be as effective as a loop. GCC does it.
Related
My code for finding 10th decimal digit of square root of 2.
#include <stdio.h>
unsigned long long int power(int a, int b);
unsigned long long int root(int a);
int main()
{
int n;
n=10;
printf("%llu \n",root(n));
return 0;
}
unsigned long long int power(int a, int b)
{
int i;
unsigned long long int m=1;
for (i=1;i<=b;i++)
{
m*=a;
}
return m;
}
unsigned long long int root(int a)
{
unsigned long long int c=1;
int counter=1;
while(counter<=a)
{
c*=10;
while(power(c,2)<=2*power(10,2*counter))
{
c++;
}
c-=1;
counter++;
}
return c;
}
I have tried the same algorithm in python. It can find the 10th decimal digit of $sqrt{2}$ immediately.
However, while doing C, I have waited for 10 mins but without a result.
Python handles big numbers for you. [1]
Although, as you say that you are getting the answer "immediately", your algorithm in python is not probably the same as the one you used in C.
#bruno's answer already explains why you are not getting the expected results in C.
[1] Handling very large numbers in Python
Exceed the range that the data can represent. when counter is equal to 10,2*power(10,2*counter) exceeds the range that unsigned long long int can represent. Python supports large number calculations, unlimited digits
you have overflow(s)
when counter values 10 you try to compute power(10,20) but even long long on 64 bits are not enough large, so you loop in
while(power(c,2)<=2*power(10,2*counter)){
c++;
}
for a long time (may be without ending)
Having long long on 64 bits allows to compute the result for n valuing up to 9
I don't understand why this code compiles and then segfaults:
#include <stdio.h>
#include <stdlib.h>
unsigned long int gcd(unsigned long int, unsigned long int);
unsigned long int lcm(unsigned long int, unsigned long int);
int main(int argc, char *argv[]) {
int i;
unsigned long int n = 1L;
for (i = 2; i < 21; i++) {
n = lcm(n, i);
}
printf("%ld\n", n);
return 0;
}
unsigned long int gcd(unsigned long int a, unsigned long int b) {
if (a == b) return a;
if (a > b) return gcd(a - b, b);
return gcd(a, b - a);
}
unsigned long int lcm(unsigned long int a, unsigned long int b) {
return abs(a * b) / gcd(a, b);
}
Are those unsigned longs even necessary? I also noted that if I change that 21 to a 18 it gives the correct result. The code is meant to find the LCM of all the numbers from 1 to 20.
Running it in gdb gives:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400643 in gcd (a=7536618, b=18) at p5.c:19
19 if (a > b) return gcd(a - b, b);
You're overflowing the stack. Which is a shame, because that should be easily optimized as tail recursion, full recursion is extremely overkill for this. Using the proper optimization levels in any modern compiler (cl, gcc, icc) should get rid of the segfault.
Luckily writing this iteratively is trivial as hell:
unsigned long gcd(unsigned long a, unsigned long b)
{
while(a != b)
if(a > b)
a -= b;
else
b -= a;
return a;
}
Due to how the stack and how they work, there's a limit on how deep function calls can be nested, depending on how much local state they keep.
For extremely imbalanced arguments, implementing gcd by repeated subtraction requires a lot of iterations, and so your recursion goes way to deep. You need to either change the implementation (e.g. make it iterative), or change the algorithm (e.g. compute remainders instead of differences).
You could increase the stack size, but that is wasteful of memory and the larger size will run eventually run out too with larger inputs.
Here is my code, for some reason I have to use unsigned long. The gdb tells me that I have
seg fault. Can one can help me? I could not find it by myself. The most interesting thing is that if I change the type to int from unsigned long, there is no seg fault.
Code is here:
#include <stdio.h>
int counting_Sort (unsigned long ary[], unsigned long array_size,unsigned long max){
unsigned long counting[max+1];
unsigned long j;
for(j=0;j<max+1;j++){
counting[j]=0;//initize to zero
}
unsigned long i;
for(i=0;i<array_size;i++){
counting[ary[i]]++;
}
unsigned long q;
for(q=1;q<max+1;q++){
counting[q]=counting[q-1]+counting[q];
}
for(q=0;q<max+1;q++){
counting[q]=counting[q]-1;
}
unsigned long outputAry[array_size];
unsigned long d;
for(d=(array_size-1); d>=0;d--){
outputAry[counting[ary[d]]]=ary[d];// SEG FAULT IS HERE
counting[ary[d]]--;//AND HERE
}
unsigned long m;
//for(m=0; m<array_size;m++){
// printf("%lu\n",outputAry[m]);
// }
return 0;
}
int main(){
unsigned long array[7]={2,6,4,0,1,7,9};
printf("before sorting the order is: \n");
unsigned long i;
for(i=0;i<7;i++){
printf("%lu\n",array[i]);
}
printf("after sorting, the new order is: \n");
counting_Sort(array,7,9);
getchar();
return 0;
}
You've found the place, just not the reason.
unsigned long d;
for(d=(array_size-1); d>=0;d--){
d is an unsigned integer, which means d>=0 is always true. The loop never ends, and that's the reason of segmentation fault.
One way is to change d to a singed type:
int d;
But if that's not what you want, change the for loop to:
for (d = 0; d <= array_size - 1; d++){
I had written this code which has the recursive function differ, when I run it, using the printf statements I notice that the code executes in the proper direction and I get the required value printed by the printf statement at the end of differ function but that value is not immediately returned instead the recursion goes again in the reverse direction and returns a wrong value. I have been struggling to debug it but I do not understand why it does not return immediately after it executes the last printf statement. Please help!!
To run enter:
5 3 1
0 3 8 5 12
1 3
as the input
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
long long int df;
long long max(long long int a,long long int b)
{
long long int maxi;
maxi = a>b ? a:b;
return maxi;
}
long long min(long long int x,long long int y,long long int *a)
{
long long int mini;
mini = a[x]<a[y] ? (x+1):(y+1);
return mini;
}
long long differ(long long int n1,long long int n2,long long int *a,long long int k,long long int n)
{
long long int df,i;
df=a[n1-1]-a[n2-1];
df=abs(df);
printf("%lld\n",df);
if(df>k)
{
for(i=0;i<n;i++)
{
if(max(a[n1-1],a[n2-1])>a[i] && (max(a[n1-1],a[n2-1])-a[i])<=k)
{
printf("%lld %lld\n",a[i],a[min(n1-1,n2-1,a)-1]);
differ(i+1,min(n1-1,n2-1,a),a,k,n);
return df; //Even this does not work
}
}
}
printf("%lld 90909\n",df);/*This does print a required value but changes again and returns a wrong value finally.*/
return df;
}
int main()
{
long long int n,k,p,f1,f2,d=0,i,j;
scanf("%lld",&n);
long long int a[n];
scanf("%lld",&k);
scanf("%lld",&p);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
while(p-- > 0)
{
scanf("%lld",&f1);
scanf("%lld",&f2);
printf("%lld df\n",d);
d = differ(f1,f2,a,k,n);
printf("%lld diff",d);
if(d<=k)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
Assigning the recursive function to df would solve the problem, that is
df=differ(i+1,min(n1-1,n2-1,a,k,n);
Hope it helps someone who is struggling with this small mistake during recursion.
Tried to develop a code that quickly finds Fibonacci values.
But the problem is I get SIGSEGV error when input is of order 1000000.
Also from other questions around here I came to know that it may be because of stack memory that exceeds limit during runtime. And I guess that is the case here.
#include<stdio.h>
unsigned long long int a[1000001] = {0};
unsigned long long int fib(int n)
{
unsigned long long int y;
if(n==1 || n==0)
return n;
if (a[n] != 0)
return a[n];
else
{
y=fib(n-1)+fib(n-2);
a[n] = y;
}
return y;
}
main()
{
int N;
unsigned long long int ans;
a[0] = 1;
a[1] = 1;
scanf(" %d",&N);
ans = fib(N+1);
printf("%llu",ans);
}
How do I fix this code for input value of 1000000?
Here's a better approach (which can still be significantly improved) that will calculate Fibonacci numbers for you:
unsigned long long Fibonacci(int n)
{
unsigned long long last[2] = { 0, 1 }; // the start of our sequence
if(n == 0)
return 0;
for(int i = 2; i <= n; i++)
last[i % 2] = last[0] + last[1];
return last[n % 2];
}
However, you are not going to be able to calculate the millionth Fibonacci number with it, because that number is much, much, much, much larger than the largest number that can fit in an unsigned long long.
Instead of using the stack, use your own variables to track state. Essentially, do the function calls and returns with your own code.
The best way really is just to switch the algorithm entirely to one that's efficient. For example, to calculate fib(6), your code calculates fib(4) twice, once when fib(5) asks and once when fib(6) asks.