I am learning C, so I am writting some little exercises in C to practice the language.
I have experience with functional code, so I love recursion. I think that it would be great to achieve tail recursion using C static variables, so additional arguments or helper functions would not be required.
This code to calculate a factorial using recursion, fails:
long long int fact(int n)
{
static long long int result = -1;
if(n <= 0) {
if(result < 0)
return 1;
else {
long long int temp = result;
result = -1;
return temp;
}
} else {
result *= n;
fact(n - 1);
}
}
However, for some reason, I cannot do this in C. Is there an idiom to the same that? Is it just my compiler? What about memoization?
Thanks a lot.
Your code is broken since it has a control path where it doesn't return a value. This works fine:
long long int fact(int n)
{
static long long int result = 1;
if(n <= 1) {
long long int temp = result;
result = 1;
return temp;
} else {
result *= n;
return fact(n - 1);
}
}
GCC does successfully transform the tail recursion to iteration.
In general, I think the reason to avoid using statics for tail recursion is simply because the function loses reentrancy. So much code ends up having to run in a multithreaded environment these days that it's hard to justify leaving function-local static "landmines" in code. I do admit this is as much opinion as technical argument. The non-static tail recursive code:
static inline long long int fact_(int n, long long int result)
{
if(n <= 1) {
return result;
} else {
return fact_(n - 1, result * n);
}
}
long long int fact(int n)
{
return fact_(n, 1);
}
is if anything a bit easier to write - notably both versions are exactly 13 LOC - and compiles just as efficiently to iteration but without needing static data.
You don't seem to have an explicit return value from your else block. Are you not getting compiler warnings on that? Please make sure you're compiling with all warnings turned on.
Basically, you need to add return result; to the end of your else block otherwise how are you going to return the result back to the original caller? Remember, return only pops one function call, and you're an arbitrary depth when you call return because of all the recursive calls to fact() you've made in your else block.
int factorial(int n)
{
static int m = 1;
m *= n;
if (n > 1)
factorial(n - 1);
return m;
}
Related
I am new to coding. so I wanted to write a c program using recursion to calculate the factorial of a number.
#include <stdio.h>
int fact(int a) {
int n = 1;
if (a != 0)
return;
else
n = n * a;
a--;
fact(a);
return n;
}
int main() {
printf("%d", fact(5));
return 0;
}
This is the program I have written. I know this is probably wrong but I think I would understand programming better if I was able to understand why the above program is exactly wrong.
Because whenever you pass any value other than 0 to fact your code exits without even returning a value:
if(a!=0)
return;
You should get at least a warning from your compiler that this is invalid code, since fact is expected to always return an int value.
But even more so, this is a logical error.
Did you mean to write:
if (a == 0) return 1; //0! = 1
Lev M. pointed out your mistakes in his answer. This is a working recursive implementation of the factorial algorithm.
unsigned int fac(unsigned char n)
{
if (n == 0)
return 1;
return n * fac(n - 1);
}
My Code
#include<stdio.h>
int isprime(long int n);
int isfib(long int n);
int main()
{
int t;
long int i;
scanf("%d",&t);
while(t--)
{
scanf("%ld",&i);
if(isprime(i))
{
printf("%d\n",isfib(i));
}
else
{
printf("0\n");
}
}
}
int isprime(long int n)
{
int j;
if(n==1)
{
return 0;
}
for(j=2;j<=n/2;j++)
{
if(n%j==0)
{
return 0;
}
}
return 1;
}
int isfib(long int n)
{
long int a=0,b=1,c=0;
while(1)
{
c=a+b;
if(c<n)
{
a=b;
b=c;
}
else if(c==n)
{
return 1;
}
else
{
return 0;
}
}
}
T is no. of test cases.
Input 3 2 4
Output 1 1 0
Code is correct. But I want to execute with O(n)complexity.
Could you please me to, how to optimize this code, I want to learn code optimization in only this c programming language.
ERROR Your program took more time than expected.
expected time>1.12Sec
For starters, you have a very slow implementation of isprime. This one is way faster:
int isprime(int n) {
if(n == 1) return 0;
int i=2;
while(i*i<n) {
if(n%i == 0)
return 0;
i++;
}
return 1;
}
I'm pretty sure you can find something similar online for the fibonacci sequence.
However, it seems like you will receive a pretty big amount of numbers. Then it's a waste checking the same number again. You can use the following idea to take advantage of that.
int isprimeandsaveresult(int n, char * arr) {
if(arr[n] == 1) return 1;
if(arr[n] == 0) return 0;
return arr[n] = isprime(n);
}
Here, arr is a huge array initialized to something else than 1 or 0. I chose char to save memory, but this can be improved further by some hash function. You can use the same principle for fibonacci numbers.
I am quite new to programming when compared to some veterans so correct me if I'm mistaken. I see no pointers in your code that means some of your variables could be converted into register storage class.
Register class variables are stored in CPU registers not in memory so for frequently used variables it is very nice for optimization. In your case "i" is strongly recommend but this can be implemented to all your variables.
This is a recursive function to find the amount of 2 appearing in a number.
Example Input:
221122
Example Output:
countTwo(): 4
#include <stdio.h>
void countTwo2(int num, int *result);
int main()
{
int number, result;
printf("Enter the number: \n");
scanf("%d", &number);
countTwo2(number, &result);
printf("countTwo2(): %d\n", result);
return 0;
}
void countTwo2(int num, int *result)
{
if(num > 0) {
if((num % 10)/2 == 1) {
*result += 1;
}
countTwo2(num/10, result);
}
}
I can't increment result since it has not been initialised but I also can't initialise result in the recursive function as this will reset the result.
Edit: This is a question given, with all the template written as above except for the code within countTwo. We are supposed to write the code in countTwo such that main() will be able to run.
Edit2: Thanks for the help! This problem has been solved by using static int. I understand that this is not very efficient. I will also ask my teacher pertaining to this question. Once again, Thanks!
The way to keep all the oddities of this code:
it has to be recursive
you cannot change main, so the initial result value will be undefined
is to, as you stated you cannot do, actually reset result inside countTwo2. However, you need to it in the right place, before you start incrementing.
The way to do that is to reorder your function and add the part that resets the value at the right place:
void countTwo2(int num, int* result)
{
if (num > 0)
{
countTwo2(num / 10, result);
if ((num % 10) / 2 == 1)
{
*result += 1;
}
}
else
*result = 0;
}
Notice that I moved the recursive call up above the if-then block that increments the result, and that when num is 0, we reset. This will call recursively down digits of the input until we're at the end, then reset the result, then return back up one digit at a time and optionally increment the value.
This requires no other changes to your code.
As many have stated, in comments and answers, this is obviously not a good implementation or design but if you have a confined context to work in, this is probably as good as it gets.
I can't see any good reason for declaring this as a void function with the result passed back via pointer parameter.
The following would be a lot cleaner, surely?
int countTwo(int num) {
return (num == 0) ? 0 : (num % 10 == 2) + countTwo(num / 10);
}
For reference, the proper way to write such a function is to not use recursion. It isn't obvious that the compiler will be able to unroll the recursion in this case, as the recursive call would be in the middle of the function, and also conditional.
Thus the only thing gained from recursion is slow execution and higher stack peak use. Why would we want slow execution when we can have fast execution? You should ask your teacher this question, so they can tell you why they are teaching it. I would be most curious to hear their rationale.
For a professional, non-academic programmer, the proper way to write the function would be to use a loop:
int count_n (int input, int n)
{
int result = 0;
for(; input>0; input/=10)
{
if(input%10 == n)
{
result++;
}
}
return result;
}
(This version doesn't work with negative numbers.)
As I mentioned before you may use static variables.
You do not need two arguments.
Here is a solution: #Lasse Vågsæther Karlsen
#include <stdio.h>
int countTwo2(long int num)
{
static int m=0; //static variable is initialized only once.
if (num==0)
return m;
else if (num % 10 ==2)
m=m+1;
num=num /10;
countTwo2(num);
}
int main()
{
int result; long int number;
printf("Enter the number: \n");
scanf("%ld", &number);
result=countTwo2(number);
printf("countTwo2(): %d\n", result);
return 0;
}
just a fibonacci algorithm, how do i print every number of fibonacci sequence without repeat every step?
Does recursive functions is a good use in any way? I know it is more legible, but there is a visible delay in this simple algorithm if i put n = 40, whereas the iterative way of doing it is instantaneous.
int fib(int n)
{
if (n == 0)
{
return 0;
}
else if (n == 1)
{
return 1;
}
return fib(n - 1) + fib(n - 2);
}
You can easily optimize the recursive solution by memoizing the already-computed values:
int fib(int n) {
static int cache[48] = {0}; // should be enough to hold all int fibs
if(n < 2) return n; // initial conditions
else if(cache[n]) return cache[n]; // a value already computed and memoized
else return cache[n] = fib(n - 1) + fib(n - 2); // the largest so far
}
Should speed up the computation by, uh, some factor.
Imperative languages like C do not always map well to functional definitions of algorithms.
Non-recursive is generally faster because both the compiler and processor can more easily optimize/parallel'ize the execution and you're not wasting energy, needlessly pushing and popping the stack. Either way, all you need are the previous two fib values to calculate the next one:
void PrintNFibs(unsigned n)
{
size_t a = 1;
size_t b = 1;
size_t sum;
printf("0\n1\n1\n");
while ( n-- )
{
sum = a + b;
printf("%zu\n", sum);
a = b;
b = sum;
}
}
It's one thing to define an algorithm in terms of itself (recursion) and another to implement it efficiently in C. For something as simple as Fibonacci however, I would not use recursion, but here's one anyway:
void PrintNFibsR(unsigned n)
{
static size_t a = 0;
static size_t b = 1;
static size_t sum;
sum = a + b;
if ( a == 0 )
{
printf("0\n1\n");
}
printf("%zu\n", sum);
if ( n > 1 )
{
a = b;
b = sum;
PrintNFibsR(n - 1);
}
}
Notice that all we're really doing here is passing the loop counter. Wasteful but technically recursive, if not actually functional. The problem with writing C code that looks just like the recursive Fibonacci algorithm definition, is it burns energy and stack space for no good reason. The only way you can print the values in the correct order without calculating and storing each one of them in advance, is to alter the algorithm.
im trying to solve this very first challange but i get stuck,
i like fast program, so i decided to use recursive method not iteration
unfortunately, when the input is a big integer (100000 > input > 1000000), its often crash
so i debug it, and it shows stack overflow error
please help me, i dont know what to do, ive tried to change data type to unsigned long, unsigned int, etc, but none of it works
here is my code,
im using ANSI C
#include "stdio.h"
int cek(int n) {
return n % 2;
}
int fung(int n,int c) {
if (n == 1) {
return c;
}
if (!cek(n)) {
return fung(n/2,++c);
}
else {
return fung((n*3)+1,++c);
}
}
int comp(int i,int j,int tmp) {
int temp;
if (i == j)
return tmp;
temp = fung(i,1);
if (temp > tmp)
return comp(++i,j,temp);
else
return comp(++i,j,tmp);
}
int main() {
int i,j,tmp;
while (scanf("%d %d",&i,&j)) {
if (i > j) {
tmp = i;
i = j;
j = tmp;
}
printf("%d %d %d\n",i,j,comp(i,j,0));
}
return 0;
}
PS: sorry for my stupidness, im really a newbie #_#
Recursion is not likely to be faster than iteration, and in fact it's likely to be slower.
The call stack has a limited size, and if your recursion goes deeper than that, there's nothing you can do about it. Especially in the Collatz problem, there's no way to tell up front how many steps you'll need. Rewrite this using an iterative method instead.
(If your compiler does tail call optimization, recursion might still work. But TCO is not required by the standard, so it will lead to unportable code. And apparently, your compiler does not optimize this particular tail call anyway.)
Not a C expert, but usually there is a call stack depth limit enforced by the compiler. Probably you can change this with a compiler flag, but this will not solve your problem. Making the algorithm iterative instead of recursive will fix it.
Recursive algorithms won't go faster than iterative ones, usually. But they are typically nicer to understand. (= more elegant)
Okay guys,
i found it!!!
so this is my code, i still use recursion but only for the inner loop fung(),
im not really impressed of it, because its need 0,5 sec to count input 1 and 1000000, someone's code outhere can do it in 0 sec, LOL
i change the outer loop comp() with iterative method,
look here
#include "stdio.h"
/*#include "windows.h"*/
int cek(int n) {
return n % 2;
}
unsigned int fung(unsigned int n,unsigned int c) {
if (n == 1) return c;
if (!cek(n)) return fung(n/2,++c);
else return fung((n*3)+1,++c);
}
/*
Above recursion will looked like this in iterative method
int func(int n) {
int c=1;
while (n != 1) {
c++;
if (n % 2 == 0)
n=n/2;
else
n=(n*3)+1;
}
return c;
}
*/
/*Outer Loop*/
int iter(int i,int j) {
int tmp1=0,tmp2;
while (i <= j) {
tmp2 = fung(i,1);
if (tmp1 < tmp2)
tmp1 = tmp2;
i++;
}
return tmp1;
}
int main() {
unsigned int i,j,s,f;
while (scanf("%d %d",&i,&j)) { /*UVa Standard, infinite loop*/
/*s = GetTickCount();*/
printf("%d %d %d",i,j,iter(i,j));
/*f = GetTickCount();
printf("%lu\n",f-s);*/
}
return 0;
}