Stirling's approximation in c language - c

I'm trying to write a code in C to calculate the accurate of Stirling's approximation from 1 to 12.
Here's my code:
#define PI 3.1416
#define EULERNUM 2.71828
float stirling_approximation(int n) {
int fact;
float stirling, ans;
fact = factorial(n);
stirling = sqrt(2.0*PI*n) * pow(n / EULERNUM, n);
ans = fact / stirling;
return ans;
}
int factorial(int input) {
int i;
int ans = 0;
for (i = 1; i <= input; i++)
ans += i;
return ans;
}
int main(void) {
int n;
printf(" n\t Ratio\n");
for (n = 1; n <= 12; n++) {
printf("n: %2d\t %f\n", n, stirling_approximation(n));
}
return 0;
}
I'm getting the recursive calculation correctly, but my Stirling's approximation method value is way off. And what's even more puzzling is the answers for n = 1, 3 is correct.
I think it has something to do with calling the approximation function from the main function. I know it must be such a simple mistake but I've been trying to fix this for the entire day! Could anyone please help me?
Thank you!

You incorrectly implemented the factorial method
int factorial(int input) {
int i;
int ans = 0;
for (i = 1; i <= input; i++)
ans += i;
return ans;
}
It should be
int factorial(int input) {
int i;
int ans = 1;
for (i = 2; i <= input; i++)
ans *= i;
return ans;
}
I would also change the return value from int to long int.

Related

Reversing digit using recursive function in C

I'm trying to create a recursive function to reverse digits of a number in C. This is what I've written. It works fine when used one time but when used multiple times it keeps piling the numbers together. I think the problem can be sorted if the sum is initialized to zero each time the function is called but I'm unable to do it. I've tried declaring sum=0 as a global variable but the result was the same.
Input-
12
23
34
45
Output
21
2132
213243
21324354
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int digit_reverse(int N)
{
int rem;
static int sum=0;
if(N>0)
{
rem=N%10;
sum=sum*10+rem;
digit_reverse(N/10);
}
else
return 0;
return sum;
}
int main()
{
int a[25],i;
for(i=0;i<4;i++)
{
scanf("%d", &a[i]);
}
printf("Output\n");
for(i=0;i<4;i++)
{
printf("%d\n",digit_reverse(a[i]));
}
}
Maybe you can write your function without using static variables:
void _digit_reverse(int N, int *sum)
{
int rem;
if (N > 0)
{
rem = N % 10;
*sum = *sum * 10 + rem;
_digit_reverse(N / 10, sum);
}
}
int digit_reverse(int N)
{
int sum = 0;
_digit_reverse(N, &sum);
return sum;
}
Or take the sum outside:
int sum = 0;
int digit_reverse(int N)
{
int rem;
if (N > 0)
{
rem = N % 10;
sum = sum * 10 + rem;
digit_reverse(N / 10);
}
else
return 0;
return sum;
}
int main()
{
int a[25], i;
for (i = 0; i < 4; i++)
{
scanf("%d", &a[i]);
}
printf("Output\n");
for (i = 0; i < 4; i++)
{
sum = 0;
printf("%d\n", digit_reverse(a[i]));
}
}
I believe that the static variable gets initialized only once. This is the problem with your approach.
dude everything looks fine to me if the code do not needs to be reusable I can think of several solutions but keep in mind static and or global variables are not best practices unless necessarily required to.
secondly change your
// from static int sum = 0;
// to
static long sum = 0;
// or
static long long sum = 0;
the reason for this error is value overflow
an integer cannot have more than 4 bytes of data in this specific case you definitly needs more.

factorial calculation in C

I wanted to write a simple program to calculate the factorial of a given number using C. Yet my code seems to have some logical error that I can't detect. Would be glad for help.
int fact(int n);
int main(void)
{
int num = get_int("Type number: ");
printf("%i\n", fact(num));
}
//define function
int fact(int n)
{
for (int i = 1; i < n; i++)
{
n *= i;
}
return n;
}
You can't use n to calculate.
You have to save total with another variable
int fact(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product = product * i;
}
return product;
}
In mathematics, the factorial of a positive integer N, denoted by N!, is the product of all positive integers less than or equal to N:
N!=N*(N-1)*(N-2)*(N-3)*.......*1
+-------------------------+
notice that this is: (N-1)! <==> So, N! = N*(N-1)!
we can use these mathematical facts to implement the factorial function in 2 different forms, recursive and iterative approaches:
recursive approach
size_t rec_factorial(size_t n)
{
/*Base case or stopping condition*/
if(n==0)
{
/* 0! = 1 */
return 1;
}
/*n! = n * (n-1)!*/
return n * rec_factorial(n-1);
}
iterative approach
size_t factorial(size_t n)
{
size_t j = 1;
size_t result = 1;
while(j <= n){
result *= j; /* n!=n*(n-1)*(n-2)*(n-3)*....1 */
++j;
}
return result;
}

Why does same program act different in ideone and codeblocks?

This code is designed to find the sum of digits of 100!. I get the correct ouput in ideone but the wrong one in codeblocks. Please help.
#include <stdio.h>
#include <stdlib.h>
#define size_of_number 160
#define question 100
//Function Prototypes
void initialise(int[]);
int sum_of_digits(int[]);
void factorial(int[],int);
int main()
{
int number[size_of_number];
int sum;
initialise(number);
factorial(number, question);
//Getting the sum of the digits of the number
sum = sum_of_digits(number);
printf("The sum of the digits of %d! is %d.\n",question, sum);
return 0;
}
//Initially, the number is 0 so all it's digits are set to zero.
void initialise(int number[])
{
int i;
for(i = 0; i < size_of_number; i++)
{
number[i] = 0;
}
}
//Finding the factorial by multiplying the digits
void factorial(int number[], int num)
{
int i, first_digit;
int carry, replace, product;
first_digit = 0;
number[first_digit] = 1;
while(num != 1)
{
carry = 0;
for(i = 0; i <= first_digit; i++)
{
product = num*number[i] + carry;
replace = product%10;
carry = product/10;
number[i] = replace;
if( (i == first_digit) && (carry > 0) )
{
first_digit++;
}
}
num--;
}
}
//Finding the sum of all digits
int sum_of_digits(int number[])
{
int i, sum;
for(i = 0; i < size_of_number; i++)
{
sum = sum + number[i];
}
return sum;
}
I had problems with some other programs too. Why s Codeblocks not giving the correct output which is 648 ?
You don't initialize sum in the function sum_of_digits. Normal local variables don't automatically get a starting value in C, so your program has what the C standard calls undefined behaviour. Anything can happen, but what typically does happen is that the variable starts with whatever data happened to be in the place in memory where the variable happened to be located.

Finding nCr value

I'm trying to find nCr value. There is no error but I'm getting 1 as the answer for all the inputs. Help me find the solution please.
#include <stdio.h>
int fact(int num)
{
int f=1,i;
for(i=1;i<=num;i++)
{
f=f*1;
}
return f;
}
int main(void)
{
int n,r,ncr=0;
printf("\n enter n and r values");
scanf("%d%d",&n,&r);
ncr=(fact(n) / (fact(r) * fact(n-r)));
printf("\n ncr for %d and %d is %d",n,r,ncr);
return 0;
}
It should not be f = f *1, but rather f = f * i
Your factorial code is incorrect.
You set f = 1, then do f = f * 1 a bunch of times. Then return f which is still 1. I think you mean f = f*i right?
int fact(int num)
{
int f=1,i;
for(i=1;i<=num;i++)
{
f=f*i;
}
return f;
}
Your method to compute factorial needs a correction. Should be :
int fact(int num)
{
int f=1,i;
for(i=1;i<=num;i++)
{
f=f*i;
}
return f;
}
Also, nCr is not defined if r > n. You should add this check after your scanf call.
Something like :
if (r > n) printf("r cannot be greater than n.").
A more standard form of computing factorial is one that uses recursion.
int fact(int num)
{
if (num == 1 || num == 0)
return 1;
else
return (num * fact(num - 1));
}
A better and faster approach would be to calculate nCr like this
int nCr(int n, int r) {
if (r > n / 2) r = n - r;
int ans = 1, i;
for (i = 1; i <= r; i++) {
ans *= n - r + i;
ans /= i;
}
return ans;
}

Custom Recursive function |returning no values at all| in C

I thought of making this An=8(An-1)*(An-1)/An-2 while a1=1,a0=1
With the following code for n=2 a2=0.0000 which is altogether wrong
On the other hand (Sum of An) S(n)=1+1+0.0000(false number) theoretically correct
#include <stdio.h>
float rec(int n);
float sum(int n);
main()
{
int n;
printf("\nInput N of term an: ");
scanf("%d",&n);
printf("\n\na%d=%f",n,rec(n));
printf("\n\nS(%d)=%f",n,sum(n));
}
float rec(int n)
{
int i;
float a[1000]={1,1};//a0=1,a1=1
if(n<0)
printf("\nNegative values of N are invalid");
else if(n==0)
return a[0];
else if(n==1)
return a[1];
else if(n>1)
for(i=2;i<=n;i++)
a[i]=((8 * a[i-1]*a[i-1]) - 1)/a[i-2];
return a[i];
}
float sum(int n)
{
int i;
float sum=0;
for(i=0;i<=n;i++)
sum+=rec(i);
return sum;
}
float a[1000]={1,1};
initializes a[0] = 1 and a[1] = 1 and rest of the elements to 0.
Now, you are returning a[i] from your function. For n=2 it will return a[3], which is 0 of course, but not the a[2] as you are expecting.
Now just change the return value to a[i-1] and it will work.
float rec(int n)
{
int i;
...
...
return a[i-1];
}
for(i=2;i<=n;i++)
a[i]=((8 * a[i-1]*a[i-1]) - 1)/a[i-2];
return a[i];
problem here, you will always get zero!!! why?
say i input 3,, now say i = 3,alls well a[3] gets calcualted, now you program goes back to the for loop, now i =4, it now does not fit the check i<=n, and so now i is 4,
you are returning a[i] which is actually a[myanswer+1]...
fix it by returning a[i-1]
At this point in rec:
return a[i];
i is 3, not 2, because it was incremented before the last test of the loop. As such you're returning the element of the array after the last one set. Be careful if you fix this by returning a[i-1] because if i is never initialized or is 0, this will cause a problem. You should clean up the rec method a bit to handle these corner cases, but the immediate problem is that i is 3, not 2.
Replace
return a[i];
with
return a[n];
(As an aside, you do not need the extra branches for 0 and 1.)
A beautiful example of Schlemiel the Painter's algorithm :)
About half the computations are done unnecessarily multiple times
The array is unnecessary and defeats the whole point of using a recursive approach
Beside, it is defined to hold 1000 values, but the function grows so fast that it will exceed a float capacity after 10 terms or so.
A more streamlined version here :
#include <stdio.h>
float A (int n, float * sum)
{
if (n <= 0) { *sum = 0; return 0; }
if (n == 1) { *sum = 1; return 1; }
if (n == 2) { *sum = 2; return 1; }
float anm2 = A(n-2, sum); // store A(n-2). sum will be overwritten by A(n-1)
float anm1 = A(n-1, sum); // store A(n-1) once to avoid calling A twice, and get preceding sum
float an = ((8 * anm1*anm1) - 1)/anm2;
*sum += an;
printf ("index %d : term %g sum %g\n", n, an, *sum);
return an;
}
int main (void)
{
int n;
float sum;
printf("\nInput N of term an: ");
scanf("%d",&n); printf("\n");
printf("\na%d=%f",n,A(n, &sum));
printf("\n\nS(%d)=%f",n,sum);
}
Beside, recursion is unnecessary and leads to inefficient and confusing code.
See a more straightforward solution here:
#include <stdio.h>
typedef struct {
float term;
float sum;
} A; // current term and sum of series A
void compute_A (int n, A * res)
{
int i;
float anm1, // a[n-1]
anm2; // a[n-2]
// special case for n<=1
if (n == 1)
{
res->sum = res->term = 1;
return;
}
if (n <= 0)
{
res->sum = res->term = 0;
return;
}
// initial terms
anm2 = anm1 = 1;
// initial sum
float sum = anm1+anm2;
// compute the remaining n-2 terms and cumulate the sum
for (i = 2 ; i <= n ; i++)
{
// curent term
float an = ((8 * anm1*anm1) - 1)/anm2;
// cumulate sum
sum += an;
// shift computation window
anm2 = anm1;
anm1 = an;
printf ("index %d : term %g sum %g\n", i, an, sum);
}
// report result
res->sum = sum;
res->term = anm1;
}
int main (void)
{
int n;
A res;
printf("\nInput N of term an: ");
scanf("%d",&n); printf("\n");
compute_A (n, &res);
printf("\na%d=%f",n,res.term);
printf("\n\nS(%d)=%f",n,res.sum);
}
float rec(int n){
static max_i = 1;
static float a[1000]={1,1};//a0=1,a1=1
int i;
if(n<0){
printf("\nNegative values of N are invalid");
return NAN;//<math.h>
}
if(n >= 1000){
printf("\nMore than 1000 are invalid");
return NAN;
}
if(n<2)
return a[n];
if(n>max_i){
for(i=max_i+1;i<=n;++i)
a[i]=((8 * a[i-1]*a[i-1]) - 1)/a[i-2];
max_i = n;
return a[n];
}
return a[n];
}

Resources