EDIT: I've added the main, factorial, and trapGamma function to give the full picture but I am specifically talking about the for loop for iSum in the I function.
Basically I've run out of ideas and exhausted everywhere I know of to find an answer to this. I need to code a program that will compute a complex function which represents an M/M/1 queue.
The function includes sub functions such as calculating the integral of a gamma function and computing factorials. I've written all the code for the computations but my sum is giving me huge numbers when I would expect nothing higher than about .35
#include <math.h>
#include <stdio.h>
double I(int k, double t);
double trapGamma(double z);
unsigned long long int factorial(unsigned int n);
int main()
{
int k;
int i = 0;
double dt = 0.1;
printf("Ikx = [ \n");
for (t = 14.0 ; t <= 15.0; t += dt)
{
printf("%f " , t);
for (k = 1 ; k <= 10 ; k++)
{
I(k, t);
printf("%f " , I(k, t));
}
printf("\n");
}
printf(" ];\n");
return (0);
}
double I(int k, double t)
{
unsigned long long int x;
unsigned int n = 20;
double numerator, y, pow1, c;
double iSum;
double Ix;
int i = 0;
iSum = 0.0;
Ix = 0.0;
a = .25 * pow(t , 2);
b = pow(a, i);
x = factorial(n);
y = trapGamma(k + i + 1);
iSum = (b / (x * y));
//This is the sum loop that I'm having trouble with, I've broke the iSum equation down for my own readability while coding right above this comment
for (i = 0; i <= 100 ; i++)
{
iSum += i;
}
Ix = (pow((.5 * t), k) ) * iSum;
return Ix;
}
/*
I've checked both the factorial and trapGamma functions and they are giving me the expected results.
*/
unsigned long long int factorial(unsigned int n)
{
if(n <= 1)
return 1;
else
return (n * factorial(n - 1));
}
double trapGamma (double z)
{
int i , N = 100;
double gamma;
double a = 0.0;
double b = 15.0;
double x1, x2, y1, y2;
double areai;
double w = (b - a) / N;
gamma = 0.0;
for (i = 1; i < N; i++)
{
x1 = a + ((i - 1) * w); //the left bound point
x2 = a + (i*w); //the right bound point
y1 = pow(x1,z - 1)*exp(-x1); //the height of our left bound
y2 = pow(x2, z - 1)*exp(-x2); //the height of our right bound
areai = ((y1 + y2) / 2.0) * (x2 - x1);
gamma += areai;
}
return gamma;
}
This is building upon another project where I used a bessel function to create the M/M/1 queue over a 60 second span so I can see what this one is supposed to be. I've checked both my trapGamma and factorial functions results on there own and they are both working as expected.
How are summations supposed to be coded?
If the intent of the posted code is to calculate the modified Bessel function I, there are some pitfalls and useful semplifications to be aware of. Given
Trying to calculate the factorial, the value of the Gamma function, their product and the powers separately for each term of the sum leads to integer overflow sooner than later.
It's better to update the value of each addend of the sum instead.
Also, given that k is a whole, we have Γ(n) = (n - 1)!
The addends are increasingly smaller and, after some iterations, too small to be added to the sum, given the limited precision of type double.
// Evaluates x^k / k! trying not to overflow
double power_over_factorial(double x, int k)
{
double result = 1.0;
for ( int i = 1; i <= k; ++i )
{
result *= x / i;
}
return result;
}
#define MAX_ITERS 20
double modified_Bessel_I(int k, double x)
{
x /= 2;
const double xx = x * x;
double partial = power_over_factorial(x, k);
double old_sum, sum = partial;
int m = 1;
do
{
old_sum = sum;
partial *= xx / ((m + k) * m);
sum += partial;
}
while ( old_sum != sum && ++m < MAX_ITERS );
return sum;
}
Testable here.
Related
I have an assignment to code a program to calculate cos(x) through the Maclaurin approximation. However I must use a function for the cos(x) and another one to calculate the exponentials that go on the denominators inside the cos(x) function. I think most of this is right, but I'm probably missing on something and I can't figure out what.
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
int fat(int);
float cosx(float);
int main()
{
float x1;
/* Original code: **x1 = x1 * 3.14159 / 180;** `transforms the value to radians` */
x1 = x1 * 3.14159 / 180; /* transforms the value to radians */
printf("Insert number:\n");
scanf("%f", &x1);
printf("Cosine of %f = %f", x1, cosx(x1));
return 0;
}
int fat(int y)
{
int n, fat = 1;
for(n = 1; n <= y; n++)
{
fat = fat * n;
}
return fat;
}
float cosx(float x)
{
int i=1, a = 2, b, c = 1, e;
float cos;
while(i < 20)
{
b = c * (pow(x,a)) / e;
cos = 1 - b;
a += 2;
e = fat(a);
c *= -1;
i++;
}
return cos;
}
If I input 0 it returns -2147483648.000000, which is clearly wrong.
First error is uninitialized variable x1, and right after that you have use:
int x1; // <<< uninitiated variable;
**x1 = x1 * 3.14159 / 180;** `transforms the value to radians
this will produce random value, you should put
int x = 0; // or some other value of your choice
In my opinion you should move x1 = x1 * 3.14159/100; after scanf("%d", x1).
Than again uninitiated value e before use.
int i=1, a = 2, b, c = 1, e;
...
b = c * (pow(x,a)) / e;
...
than you have in the line b = c * pow(x,a) where you go out of range of int variable potentially. If e = 1, x = 2 and a > 31 you are out of range for b. Another problem is pow(x,a) is rising much faster than `e. thus you get bigger and bigger values thus you are getting another overflow. And here is the code that works:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
long double fact(int);
long double cosx(double);
long double my_pow (double b, int e);
int main()
{
double x1 = 45.00;
printf("Insert number:\n");
scanf("%lf", &x1);
x1 = x1 * 3.14159 / 180; // ** `transforms the value to radians`
printf("Cosine of %f = %.10LF", x1, cosx(x1));
return 0;
}
long double fact(int y)
{
int n;
double fact = 1;
for(n = 1; n <= y; n++)
{
fact *= n;
}
return fact;
}
long double cosx(double x)
{
int a = 2, c = -1;
long i = 0, lim = 500;
long double cos = 1;
long double b = 0, e = 0;
while(i < lim) {
e = fact(a);
b = c * my_pow(x,a);
cos += b/e;
// printf ("%le %le %le\n", e, b, cos);
a += 2;
c *= -1;
i++;
}
return cos;
}
long double my_pow (double b, int e) {
long double pow = 1;
for (;e > 0; --e, pow *= b)
;
return pow;
}
my professor gave me a confusing problem and I'm completely lost on what to do. Basically he wants me to solve cos(x) and exp(x) (he gave an example for sinx) without using the built in math.h functions. Not only that, but he wants me to use both the fact() and power() functions to solve it. I could most likely solve it through straight math but I'm a bit lost on using the functions. I understand the general concept but I suck at math (especially trig) and I'm not exactly sure what they functions are doing arithmetically. Any helps or points to the right direction will be greatly appreciated.
#include <stdio.h>
#include <math.h>
int main()
{
char more;
double x, mySin(), myCos(), myExp();
printf("\n\n\t\tInput X: ");
scanf("%lf", &x);
do {
printf("\n\n\t\t\tLibraryResult MyResult");
printf("\n\n\tsin< %5.2f> %7.5f %7.5f", x, sin(x), mySin(x));
printf("\n\n\tcos< %5.2f> %f %f", x, cos(x), myCos(x));
printf("\n\n\texp< %5.2f> %f %f", x, exp(x), myExp(x));
printf("\n\n\t\tDo More (Y/N)? ");
scanf("%s",&more);
}
while (more == 'y'||more == 'Y');
}
double power(double x, int n)
{
int i = 0;
double prod = 1.;
for ( ; i++ < n; )
prod = prod * x;
return prod;
}
double fact (int n)
{
int i;
double prod = 1.;
for (i = 1; i <= n; i++)
prod = prod * i;
return prod;
}
double mySin(double x)
{
int i, sign;
double sum = 0;
for (i = 0, sign = 1; i < 21; i++, sign = -sign)
sum = sum + sign * power(x, 2 * i + 1)/ fact(2 * i + 1);
return sum;
}
double myCos(double x)
{
}
double myExp(double x)
{
}
I'm trying to integrate the function 1/((1+x^2)x^0.5) using the trapezium rule. I need the precision to be as great as possible so I am therefore increasing the number of strips, N, until the computer cannot recognise a change between the total for consecutive N. However, the end condition is not currently working, leading to continuous integration. Does anyone have any better suggestions than my current code?
Many thanks,
Beth
#include<stdio.h>
#include<math.h>
#include<float.h>
double inter(double x, double h, double y, double N, double total)
{
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
while (x<y)
{
total=total+(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
//printf("x - %.16lf \n", x);
}
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
total=total*h;
//printf("t - %lf \n", total);
return total;
}
main()
{
double x,y,total,h,value,newvalue,f, N;
int finish;
x=0.1;
y=1000;
total=0;
N=1000;
finish=0;
value=0;
while(finish==0)
{
h=(y-x)/(N-1);
newvalue=inter(x,h,y,N,total);
printf("h-%.16lf\n", h);
printf("N-%.16lf\n", N);
printf("New value %.16lf\n", newvalue);
printf("c-%.16lf\n", value);
if(value==newvalue)
{
finish=1;
printf("finish-%d\n", finish);
}
else
{
value=newvalue;
newvalue=newvalue-3;
N=N+1000;
printf("newvalue-%lf\n", newvalue);
printf("value-%lf\n", value);
}
}
printf("%lf\n", value);
}
If you wish to create an automatic refinement of your numerical integration, one technique is to look at the relative convergence of your integration.
double previous = 0;
double current = inter( x, (y-x)/(N-1), y, N, total ); // Solve some baseline
do
{
N = N + 1000;
h = (y-x)/(N-1);
previous = current;
current = inter( x, h, y, N, total );
} while( abs( current - previous ) / current > 0.001 );
That code will stop after you observe less than 0.1% relative refinement in your estimation. Decreasing 0.001 will effectively increase your accuracy. Usually the best way to compare doubles is through a tolerance check like:
abs( a - b ) < k
where k is some factor of the order of accuracy you wish to achieve.
This integral is difficult because the f(x) -> ∞ as x -> 0. In this example, I changed the range to 1 to 1000. I also used a summation function to minimize rounding error when summing up a large number of values. The integral from wolframalpha ~= .487474, this program results in ~=.487475 . The exact integral can be found using this link:
integral 1/((1+x^2)sqrt(x))
#include<stdio.h>
#include<math.h>
#include<float.h>
/* clear array */
void clearsum(double asum[2048])
{
size_t i;
for(i = 0; i < 2048; i++)
asum[i] = 0.;
}
/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
while(1){
/* i = exponent of d */
i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
if(i == 0x7ff){ /* max exponent, could be overflow */
asum[i] += d;
return;
}
if(asum[i] == 0.){ /* if empty slot store d */
asum[i] = d;
return;
}
d += asum[i]; /* else add slot to d, clear slot */
asum[i] = 0.; /* and continue until empty slot */
}
}
/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
for(i = 0; i < 2048; i++)
sum += asum[i];
return sum;
}
double fx(double x)
{
return 1./((1.+x*x)*sqrt(x));
}
double inter(double x, double y, double n)
{
double asum[2048]; /* for summation functions */
double h;
double d;
if(n < 1.){
n = 1.;
h = 0.;
} else {
h = (y-x)/(n-1.0);
}
y -= h/2.;
clearsum(asum);
d = .5*h*fx(x);
addtosum(d, asum);
for( ; x < y; x += h){
d = h*fx(x);
addtosum(d, asum);
}
d = .5*h*fx(x);
addtosum(d, asum);
d = returnsum(asum);
return d;
}
int main()
{
double x,y,n,value,newvalue;
x=1.0;
y=1000.;
value=0.;
for(n = 100000000.; 1; n += 100000000.)
{
newvalue=inter(x,y,n);
printf("new value %.16lf %.0lf\n", newvalue, n);
if(fabs(newvalue-value) < (newvalue*1E-7))
break;
value = newvalue;
}
return 0;
}
Using Simpson's rule, the results are more accurate and converge at much smaller values for n:
#include<stdio.h>
#include<math.h>
#include<float.h>
/* clear array */
void clearsum(double asum[2048])
{
size_t i;
for(i = 0; i < 2048; i++)
asum[i] = 0.;
}
/* add a number into array */
void addtosum(double d, double asum[2048])
{
size_t i;
while(1){
/* i = exponent of d */
i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
if(i == 0x7ff){ /* max exponent, could be overflow */
asum[i] += d;
return;
}
if(asum[i] == 0.){ /* if empty slot store d */
asum[i] = d;
return;
}
d += asum[i]; /* else add slot to d, clear slot */
asum[i] = 0.; /* and continue until empty slot */
}
}
/* return sum from array */
double returnsum(double asum[2048])
{
double sum = 0.;
size_t i;
for(i = 0; i < 2048; i++)
sum += asum[i];
return sum;
}
double fx(double x)
{
return 1./((1.+x*x)*sqrt(x));
}
double simpson(double x, double y, double n)
{
double asum[2048]; /* for summation functions */
double h;
double a;
if(n < 1.){
n = 1.;
h = 0.;
} else {
h = (y-x)/(n-1.0);
}
y += h/2.;
clearsum(asum);
for( ; x < y; x += h){
a = h/6.*(fx(x) + 4.*fx(x + h/2.) + fx(x + h));
addtosum(a, asum);
}
a = returnsum(asum);
return a;
}
int main()
{
double x,y,n,value,newvalue;
x=1.0;
y=1000.;
value=0.;
for(n = 1000.; 1; n += 1000.)
{
newvalue=simpson(x,y,n);
printf("new value %.16lf %.0lf\n", newvalue, n);
if(fabs(newvalue-value) < (newvalue*1E-10))
break;
value = newvalue;
}
return 0;
}
I am tyring to make velocity Verlet method, by using C language.
I thought I made it good. However, there pops up 'Segmentation fault(core dumped)' whenever, I increase the size of the vector or array, x and y.
For the size n equal and less than 1e3, it's fine, but at the point of n = 1e4, the program gets error.
Please anybody help me on this.
Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double verlet(double t, double x)
{
double E = 0.252;
double B = 0.052;
double a = M_PI/2;
return -sin(x) + E*cos(t) + B*cos(2*t+a);
}
double pverlet(double(*f)(double, double), double dt, double t, double x, double y)
{
return x + dt*( y + (dt/2)*f(t, x));
}
double vverlet(double(*g)(double, double), double dt, double t, double x, double y)
{
return y + (dt/2) * g(t, x);
}
int main(void)
{
int i;
double t;
int n = 1e4;
double ti = 0, tf = 1e5, dt = (tf-ti)/n;
double *x = (double *) malloc(sizeof(double)*n);
double *y = (double *) malloc(sizeof(double)*2*n);
if (x == NULL)
{
printf("error allocating memory!\n");
return 1;
}
if (y == NULL)
{
printf("error allocating memory!\n");
return 1;
}
for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
for (x[0] = 0, i = 1; i < n; i++)
{
x[i] = pverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[2*(i-1)]);
}
for (i = 0; i < n; i++)
{
t = ti + dt * i;
printf("%e %e %e\n", t, x[i], y[2*i]);
}
return 0;
free(x);
free(y);
}
for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
x is defined from 0 to n-1.
I have a homework to implement an FIR filter in C and I wonder whether you think I understood the assignment correctly. The program I wrote that I think solves the problem is:
#include <stdio.h>
float FIRfloats[5];
void floatFIR(float newsample)
{
int i;
float sum=0;
FIRfloats[0]=newsample*0.0299;
FIRfloats[1]=FIRfloats[2]*0.4701;
FIRfloats[2]=FIRfloats[3]*0.4701;
FIRfloats[3]=FIRfloats[4]*0.0299;
/* sum */
for(i=0;i<5;i++)
{
sum=sum+FIRfloats[i];
}
printf("Sum: %f\n", sum);
}
int main ()
{
float n=0.0f;
while (scanf("%f", &n) > 0)
{
floatFIR(n);
}
return 0;
}
And the specification is
Before a new sample xk arrives the old samples are shifted to the
right and then each sample is scaled with a coefficient before the
result yk, the total sum of all scaled samples, is calculated
Coefficients should be c0=0.0299, c1=0.4701, c2=0.4701, c3=0.0299.
Do you think that I solved the assignment correctly? I think it seemed too easy and therefore I wonder.
I'm afraid the implementation provided in the question will not provide the correct results.
In FIR (Finite Impulse Response) filter with 4 coefficients the output series (y) for input series (x) is:
y[t] = c0*x[t] + c1*x[t-1] + c2*x[t-2] + c3*x[t-3]
Therefore the implementation should be similar to:
/* add includes (stdio.h and whatever else you'll need...) */
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
y = y + (coef[i] * x[i]);
}
x[0] = inVal;
y = y + (coef[0] * x[0]);
return y;
}
main(int argc, char** argv)
{
float coef[4] = {0.0299, 0.4701, 0.4701, 0.0299};
float x[4] = {0, 0, 0, 0}; /* or any other initial condition*/
float y;
float inVal;
while (scanf("%f", &inVal) > 0)
{
y = floatFIR(inVal, x, coef, 4);
}
return 0;
}
This does the shift and multiplication at the same loop (which does not affect results - only is more efficient.)
If you want to follow the spec exactly, you can change floatFir like this:
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
}
x[0] = inVal;
for (int i = 0 ; i < len ; i++)
{
y = y + (coef[i] * x[i]);
}
return y;
}