1D Adaptive Mesh Refinement in C - c

I am a Physics PhD student currently entering the field of numerical relativity and I have to implement an adaptive mesh refinement code in 2 dimensions. As with every other bit of my program, I usually prefer to do something much simpler to understand what is going on before jumping to a more sophisticated case. However, I still seem to be doing something fundamentally wrong.
My code performs (or at least should perform) the following procedure: I discretize the x-axis in N intervals of size h. Every time a point is computed, the program stops and computes that point again by changing the interval of size h to another interval with two steps h/2. The program checks if the results are below some user specified tolerance and, if not, the process starts again with step size h/4 and so on. The following sketch illustrates the procedure
After the refinement function acts, I have absolutely no interest in keeping the values of the function on the refined grids. All I want is to compute the function on the coarse grid with maximum accuracy (in the image all I want to keep - and change - are the values of the black dots of the coarse [base] grid).
Unfortunately I see no improvement on the solution after the refinement algorithm is passed. I do not expect the plot of the function to be perfect, but I expect every point to be very close to the analytic solution. This is my refinement function (the function is called recursively until a maximum level of refinement - user specified - is reached):
void refine( int l, long double dx, long double x_min, long double x_max, long double f_min, long double *f_max ){
// l = level of refinement, dx = step size, x_min is current x position, x_max = point we want to calculate, f_min = function evaluated at x_min, f_max = function evaluated at x_max
int i;
long double *f_aux, f_point;
f_aux = (long double *) malloc ( (2*l + 1) * sizeof (long double) );
dx = 0.5 * dx;
f_aux[0] = f_min;
for( i=1; i<2*l+1; i++ ){
f_aux[i] = ( 1.0 - 2.0 * dx * ( x_min + (i-1)*dx - X0 ) / DELTA ) * f_aux[i-1];
}
if( l < lMAX ){
if( fabs( f_aux[2*l] - *f_max ) > TOL ){
f_point = f_aux[2*l];
free( f_aux );
l++;
refine( l, dx, x_min+dx, x_max, f_min, &f_point );
}
else{
*f_max = f_aux[2*l];
free( f_aux );
}
}
else{
*f_max = f_aux[2*l];
free( f_aux );
}
return;
}
Can anyone shed some light on the problem? I feel completely stuck.
Thanks in advance!

It looks that your iteration enhances around last point, but is still coarse around start point:
*---------------* refine 0
*-------*-------* refine 1
*-------*---*---* refine 2
*-------*---*-*-* refine 3
And as your equation looks hyperbolic (depends on all previous iterations) the solution error will be cumuluative in nature. I think you shall iterate with fine grid from the begining to get proper solution - not only around neighborhood. Eg. for simple equation df/dx=f with such implementation:
float update(float f_prev, float dx, float /* unused */ target_dx) {
return f_prev*dx + f_prev;
}
int main(void)
{
int n = 8;
float dx = 2.f/(float)(n-1);
float f[n];
f[0] = 1.f;
for (int i = 1; i < n; i++) {
f[i] = update(f[i-1], dx, dx / 16.f);
}
return 0;
}
I would go with simple recursive formula:
float update_recursive(float f_prev, float dx, float target_dx) {
if (dx > target_dx) {
return update_recursive(
update_recursive(f_prev, dx / 2.f, target_dx), dx / 2.f, target_dx
);
}
return dx * f_prev + f_prev;
}
The approach enhances the quality of solution. The terminating condition may be more adaptive to solution than target_dx is. Of course, it is needed to ensure that recursion is well bounded.

Related

Exceeding the range of long double and big floating point numbers

Problem statement: I am working on a code that calculates big numbers. Hence, I am easily get beyond the maximum length of "long double". Here is an example below, where part of the code is given that generates big numbers:
int n;
long double summ;
a[1]=1;
b[1]=1;
c[1] = 1; //a, b, c are 1D variables of long double types
summ=1+c[1];
for(n=2; n <=1760; n++){
a[n]=n*n;
b[n]=n;
c[n] = c[n-1]*a[n-1]/b[n]; //Let us assume we have this kind of operation
summ= summ+c[n]; //So basically, summ = 1+c[1]+c[2]+c[3]+...+c[1760]
}
The intermediates values of summ and c[n] are then used to evaluate the ratio c[n]/summ for every integer n. Then, just after the above loop, I do:
for(n=1;n<=1760;n++){
c2[n]=c[n]/summ; //summ is thus here equals to 1+c[1]+c[2]+c[3]+...+c[1760]
}
Output: If we print n, c[n] and summ, we obtain inf after n=1755 because we exceed the length of long double:
n c[n] summ
1752 2.097121e+4917 2.098320e+4917
1753 3.672061e+4920 3.674159e+4920
1754 6.433452e+4923 6.437126e+4923
1755 1.127785e+4927 1.128428e+4927
1756 inf inf
1757 inf inf
1758 inf inf
1759 inf inf
1760 inf inf
Of course, if there is an overflow for c[n] and summ, I cannot evaluate the quantity of interest, which is c2[n].
Questions: Does someone see any solution for this ? How do I need to change the code so that to have finite numerical values (for arbitrary n) ?
I will indeed most likely need to go to very big numbers (n can be much larger than 1760).
Proposition: I know that GNU Multiple Precision Arithmetic (GMP) might be useful but honestly found too many difficulties trying to use this (outside the field), so if there an easier way to solve this, I would be glad to read it. Otherwise, I will be forever grateful if someone could apply GMP or any other method to solve the above-mentioned problem.
NOTE: This does not exactly what OP wants. I'll leave this answer here in case someone has a similar problem.
As long as your final result and all initial values are not out of range, you can very often re-arrange your terms to avoid any overflow. In your case if you actually just want to know c2[n] = c[n]/sum[n] you can re-write this as follows:
c2[n] = c[n]/sum[n]
= c[n]/(sum[n-1] + c[n]) // def. of sum[n]
= 1.0/(sum[n-1]/c[n] + 1.0)
= 1.0/(sum[n-1]/(c[n-1] * a[n-1] / b[n]) + 1.0) // def. of c[n]
= 1.0/(sum[n-1]/c[n-1] * b[n] / a[n-1] + 1.0)
= a[n-1]/(1/c2[n-1] * b[n] + a[n-1]) // def. of c2[n-1]
= (a[n-1]*c2[n-1]) / (b[n] + a[n-1]*c2[n-1])
Now in the final expression neither argument grows out of range, and in fact c2 slowly converges towards 1. If the values in your question are the actual values of a[n] and b[n] you may even find a closed form expression for c2[n] (I did not check it).
To check that the re-arrangement works, you can compare it with your original formula (godbolt-link, only printing the last values): https://godbolt.org/z/oW8KsdKK6
Btw: Unless you later need all values of c2 again, there is actually no need to store any intermediate value inside an array.
I ain't no mathematician. This is what I wrote with the results below. Looks to me that the exponent, at least, is keeping up with your long double results using my feeble only double only...
#include <stdio.h>
#include <math.h>
int main() {
int n;
double la[1800], lb[1800], lc[1800];
for( n = 2; n <= 1760; n++ ) {
lb[n] = log10(n);
la[n] = lb[n] + lb[n];
lc[n] = lc[n-1] + la[n-1] - lb[n];
printf( "%4d: %.16lf\n", n, lc[n] );
}
return 0;
}
/* omitted for brevity */
1750: 4910.8357954121602000
1751: 4914.0785853634488000
1752: 4917.3216235537839000
1753: 4920.5649098413542000
1754: 4923.8084440845114000
1755: 4927.0522261417700000 <<=== Take note, please.
1756: 4930.2962558718036000
1757: 4933.5405331334487000
1758: 4936.7850577857016000
1759: 4940.0298296877190000
1760: 4943.2748486988194000
EDIT (Butterfly edition)
Below is a pretty simple iterative function involving one single and one double precision float values. The purpose is to demonstrate that iterative calculations are exceedingly sensitive to initial conditions. While it seems obvious that the extra bits of the double will "hold-on", remaining closer to the results one would get with infinite precision, the compounding discrepancy between these two versions demonstrate that "demons lurking in small places" will likely remain hidden in the fantastically tiny gaps between finite representations of what is infinite.
Just a bit of fun for a rainy day.
int main() {
float fpi = 3.1415926535897932384626433832;
double dpi = 3.1415926535897932384626433832;
double thresh = 10e-8;
for( int i = 0; i < 1000; i++ ) {
fpi = fpi * 1.03f;
dpi = dpi * 1.03f;
double diff = fabs( dpi - fpi );
if( diff > thresh) {
printf( "%3d: %25.16lf\n", i, diff );
thresh *= 10.0;
}
}
return 0;
}
8: 0.0000001229991486
35: 0.0000010704333473
90: 0.0000100210180918
192: 0.0001092634900033
229: 0.0010121794607585
312: 0.0100316228017618
367: 0.1002719746902585
453: 1.0056506423279643
520: 10.2658853083848950
609: 103.8011477291584000
667: 1073.9984381198883000
736: 10288.9632129669190000
807: 101081.5514678955100000
886: 1001512.2135009766000000
966: 10473883.3271484370000000

Calculating potential energy in a molecular dynamics simulation

Background
Imagine that we have N particles inside a box of length L, which interact with each other (through a Lennard Jones potential).
I want to compute the total potential energy of the system. I implemented the function POT which calculates all the contributions from all the particles and gives the correct results (this is tested and can be assumed true).
I also wrote a function POT_ONE which only calculates the potential energy of one particle with respect to all the others. This means that if I want to calculate the total potential energy I will have to call this function N times (making sure that the particle does not interact with itself) and then divide by 2 since I double count the interactions.
Goal
My goal is to make the second function yield the same results as the first one.
Problem
There is something really strange going on: If I put 4 particles, the two functions give the same results. If I put a fifth one then there is deviation. Then for 6,7,8 particles,again, it gives correct results and then for N=9 I am getting a different result. In the case N=1000 the result that I am getting from POT_ONE is somemthing like 113383820348202024.
My results for N=5 are:
-0.003911 with POT and
12.864234 with POT_ONE
In case someone tries to run the code and wants to check the N=4 case, he/she should change the number of particles (np) which is defined as global variable and then comment the line pos[12]=1;pos[13]=1;pos[14]=1;.
Code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*GENERAL PARAMETERS*/
int dim=3; //number of dimensions
int np=5; //number of particles
double L=36.413; //box length (A)
double invL=1/36.413; //inverse of box length
/*ARGON CHARACTERISTICS*/
double sig=3.4; // Angstroms (A)
double e=0.001; // eV
double distSQ(double array[]){
/*calculates the squared distance given the array x=[dx,dy,dz]*/
int i;
double r2=0;
for(i=0;i<dim;i++) r2+=array[i]*array[i];
return r2;
}//distSQ
void MIC(double dr[],double L, int dim){
/* MINIMUM IMAGE CONVENTION: dr[] is the array dr = [dx,dy,dz] describing relative
positions of two particles, L is the box length, dim the number
of dimensions */
int i;
for(i=0;i<dim;i++) dr[i]-=round(dr[i]*invL)*L;
}//MIC
void POT(double x1[],double* potential){
/*given the positions of each particle in the form x=[x0,y0,z0;x1,y1,z1;...;xn-1,yn-1,zn-1],
the number of dimensions dim and particles np, it calculates the potential energy of the configuration*/
//variables for potential calculation
int i,j,k;
double *x2;
double r2inv; // 1/r^2
double foo,bar;
double dr[dim];
*potential=0; // set potential energy to zero
//main part of POT
for(i=0;i<np-1;i++){
x2=x1+dim;
for(j=i+1;j<np;j++){
//calculate relative distances between particles i & j
//apply periodic BCs and then calculate squared distance
//and the potential energy between them.
for(k=0;k<dim;k++) dr[k] = x2[k]-x1[k];
MIC(dr,L,dim); //periodic boundary conditions
r2inv=1/distSQ(dr);
//calculate potential energy
foo = sig*sig*r2inv;
bar = foo*foo*foo;
*potential+=bar*(bar-1);
}//for j
x1+=dim;
}//for i
*potential*=4*e; //scale and give energy units
}//POT
void POT_ONE(int particle,double pos[],double* potential){
*potential=0;
int i,k;
double dr[dim];
double r2inv,foo,bar;
double par_pos[dim];
int index=particle*dim;
par_pos[0]=pos[index];
par_pos[1]=pos[index+1];
par_pos[2]=pos[index+2];
for(i=0;i<np;i++){
if(i!=particle){
for(k=0;k<dim;k++) dr[k]=pos[k]-par_pos[k];
MIC(dr,L,dim);
r2inv=1/distSQ(dr);
foo=sig*sig*r2inv;
bar=foo*foo*foo;
*potential+=bar*(bar-1);
}
pos+=dim;
}
*potential*=4*e; //scale and give energy units
}//POT_ONE
int main(){
int D=np*dim;
double* pos=malloc(D*sizeof(double));
double potential=0; //calculated with POT
double U=0; ////calculated with POT_ONE
double tempU=0;
pos[0]=0;pos[1]=0;pos[2]=0;
pos[3]=4;pos[4]=0;pos[5]=0;
pos[6]=0;pos[7]=4;pos[8]=0;
pos[9]=0;pos[10]=0;pos[11]=4;
pos[12]=1;pos[13]=1;pos[14]=1;
POT(pos,&potential);
printf("POT: %f\n", potential);
int i,j;
for(i=0;i<np;i++){
POT_ONE(i,pos,&tempU);
U+=tempU;
}
U=U/2;
printf("POT_ONE: %f\n\n", U);
return 0;
}
Your error is in POT, where you forgot to update x2 at the end of the inner loop.
for (i = 0; i < np - 1; i++) {
double *x2 = x1 + dim;
for (j = i + 1; j < np; j++) {
// ... calculate stuff ..
x2 += dim;
}
x1 += dim;
}
An easier and arguably more readable variant is to forgo pointer arithmetic altogether and use boring old indices:
for (k = 0; k < dim; k++) {
dr[k] = x[j * dim + k] - x[i * dim + k];
}
Further observations:
Please make your variables local to the scope where they are used. A large list of uninitialized variables at the top of the function makes it very hard to track variables, even in a short function like yours.
Please consider returning single values from functions instead of passing in pointers. In my opinion, that makes functions like the square of the distance more readable.
The structure of your code is hard to see, because everything is run togeher very tightly, even the comments.

Best way to calculate Bernoulli's nTh numbers in C with CodeBlocks on Windows 10 Pro

Good night, I'm working in a project that needs to calculate the Bernoulli numbers for nTh order. I tried exhaustively a lot of algorithms on internet, mostly it's in C++ what's not usefull for me. And always I'd got compilations erros or the wrong results to the numbers! What is the fastest way to calculate it? Odd's numbers is always 0.00000 and I need to calculate for any even numbers... I just need the result of the number I put on the function, don't need to list the numbers until the nTh like every algorithm I saw on the internet does. The last I tried that had compilation erros and after fixed give me wrong answers above... Yes, for people that will ask me if I put the libraries on the code, yes, I did it! The problem is not libraries, it's wrong algorithms. I'm using C on GCC mingw 32-bits on Code::Blocks for Windows 10 Pro.
#include <float.h>
#include <math.h>
void bernoulli_B( int iMax, double* dB )
{
dB[0] = 1.0;
dB[1] = -0.5;
for( int j = 3; j <= iMax; j += 2 )
dB[j] = 0.0;
const double eps = DBL_EPSILON;
const double TwoPi = 6.2831853071795860;
double dCoeff = 2.0 / (TwoPi * TwoPi);
double d2 = 2.0;
for( int n = 1; n <= iMax/2; n++ )
{
double g1 = 1.0,
g2 = 1.0;
for( int j = 0; j < n; j++ )
{
g1 *= 4.0;
g2 *= 9.0;
}
double S1 = 1.0 - 1.0/g1,
S2 = S1 + 1.0/g2, S3;
double T1 = S1 + 1.0/(g2 + g1),
T2;
long r = 4;
double s = -1.0;
int nSuccess = 0;
while( !nSuccess )
{
double r2 = double(r*r);
double g3 = 1.0;
for( int j = 0; j < n; j++ )
g3 *= r2;
S3 = S2 + s/g3;
T2 = S2 + s/(g3 + g2);
if( fabs(T2-T1) > eps*fabs(T2) )
{
g2 = g3;
S2 = S3;
T1 = T2;
s = -s;
r++;
}
else
{
nSuccess = 1;
}
}
d2 /= 4.0;
dB[2*n] = 2.0 * dCoeff / (1.0-d2) * T2;
dCoeff *= -double((2*n+1)*(2*n+2)) / (TwoPi * TwoPi);
}
}
I've never worked with this type of stuff before, but on the series I'am working requires the Bernoulli numbers. So I don't have many sure what I'm doing to find those numbers. It's not my area. Probably I made some stupid thing here.
I'll tell you how I fall in this problem of Bernoulli, I'm originally working on Riemann Zeta's function. I made the C code but it only worked for >1, So I started to study how to calculate for Negative odd's, and I saw that Bn(Bernoulli numbers of N order) are in the formulae! I don't know how to calculate Bernoulli Numbers, and when I started to code Zeta's function I didn't know nothing about Bernoulli!
My advice is to use a library or package to carry out this computation; it is easy to write some code for a mathematical function which handles simple cases, and very difficult and time-consuming to handle all cases correctly. Presumably the calculation of Bernoulli numbers is just something you need to make progress on your real topic of interest. If so, you're better off finding an existing library or package. (Even you are having trouble with a library, it is still far easier to solve that problem instead of having to reimplement the algorithm.)
Sage (https://sagemath.org) can calculate Bernoulli numbers, and probably has a lot of other number theory stuff. See also Maxima (http://maxima.sourceforge.net) and maybe also GAP and PARI-GP (a web search will find those).

Iteration stuck at the 16512th iteration when 100000 iterations are supposed to be made

I am pretty flabbergasted as to why my code got stuck at the 16512th iteration even though it seemed to have no syntactical problems. Here is the code:
#include <stdio.h>
/*C version of Newton-Raphson method*/
float sqrt(float num);
main()
{
int i;
for (i = 1; i <= 100000; i++) {
printf("%d: %.3f\n", i, sqrt(i));
}
}
float sqrt(float num)
{
float guess, e, upperbound;
guess = 1;
e = 0.001;
do
{
upperbound = num / guess;
guess = (upperbound + guess) / 2;
} while (!(guess * guess >= num - e &&
guess * guess <= num + e));
return guess;
}
The code is supposed to find the square-root of all numbers from 1 to 100000 using the Newtonian-Raphson method, but nothing happened after the 16152th iteration. I am using the Developer Command Prompt for VS2012 to compile my scripts, if that information is of any help. Enlightenment will be gladly appreciated.
Honestly, when I posted mycomment, it was more a hunch than real knowledge. The algorithm was valid, so something must be making the while loop not terminate, and since you were properly using epsilons, we were hitting the limits from the float.
#PaulR's comments make it make more sense. The sqrt of 16512 is 128.499027233672... Float has fairly limited precision, so it wasn't getting anything within .001 of that number. It makes even more sense if you think of an even bigger number, e.g. sqrt(123455555.54321) (which is 11111.11111). Floating point precision won't necessarily even get you to the 11111, let alone 11111.111.
Changing to double "fixes" this, but just kicks the can down the road. Somewhere later on, we'd have the same precision issue, and this algorithm should work on any size number.
#mrbratch brings up the robust solution - define your tolerance as a percentage of the number. If you set e = num * 0.00001, your loop will always complete. Obviously, you can play with epsilon and tweak it to your satisfaction. And note, for big numbers, this can give you an integer that's not even the closest int to the right answer.
I can't speak for python, but I can confirm that javascript uses double precision.
As already explained in the comments, the problem is because you can't have that much precision (0.001) with any number. In particular, when the number is large enough, only the most important digits are saved. See the IEEE 754 standard if you want more information about how it works. http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Now, I'd recommend that you use a percentage of error for the tolerance:
float sqrt(float num)
{
float guess, e, upperbound;
guess = 1;
e = 0.001;
do
{
upperbound = num / guess;
guess = (upperbound + guess) / 2;
} while (!(guess * guess / num >= 1 - e &&
guess * guess / num <= 1 + e));
return guess;
}
Simple adjustment
Use relative Floating Point precision, not absolute.
There area as many FP representable numbers between 0.001 and 0.002 as between 1,000 and 2,000. So when calculating square root, the iterations should depend on the local relative error.
Do not use absolute error bounds like e = 0.001, but relative ones. Code then runs just fine.
// e = 0.001;
e = 0.001 * num;
[edit] I know see #Scott Mermelstein has a similar comment.
IMHO, the squaring causes loss of precision:
#include <stdio.h>
/*C version of Newton-Raphson method*/
float mysqrt(float num); /* avoid conflicts with built-in sqrt() if any */
int main(void)
{
int i;
for (i = 1; i <= 100000; i++) {
printf("%d: %.3f\n", i, (double)mysqrt(i)); /* cast to double, since printf() is varargs */
}
return 0;
}
float mysqrt(float num)
{
float newguess, e, oldguess;
e = 0.001;
newguess = 1.0;
do
{
oldguess = newguess;
newguess = (num/oldguess + newguess ) / 2;
/* compare tor the previous value; avoid squaring */
} while (newguess / oldguess > (1+e) || oldguess / newguess > (1+e) );
// } while (newguess < oldguess -e || newguess > oldguess +e); // "mostly works"
return newguess;
}

How to Approximate e in an Infinite Series in C

So I am trying to do this problem:
However, I'm not entirely sure where to start or what exactly I am looking for.
In addition, I was told I should expect to give the program inputs such as: zero (0), very small (0.00001), and not so small (0.1).
I was given this: http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 as a reference, but that formula doesn't look exactly like the one in the problem.
And finally, I was told that the input to the program is a small number Epsilon. You may assume 0.00001f, for example.
You keep adding the infinite series until the current term's value is below the Epsilon.
But all in all, I have no clue what that means. I somewhat understand the equation on the wiki. However, I'm not sure where to start with the problem given. Looking at it, does anyone know what kind of formula I should be looking to use in C and what "E" is and where it comes into play here (i.e. within the formula, I understand it's suppose to be the user input).
Code So Far
#include <stdio.h>
#include <math.h>
//Program that takes in multiple dates and determines the earliest one
int main(void)
{
float e = 0;
float s = 0;
float ct = 1;
float ot= 1;
int n = 0;
float i = 0;
float den = 0;
int count = 0;
printf("Enter a value for E: ");
scanf("%f", &e);
printf("The value of e is: %f", e);
for(n = 0; ct > e; n++)
{
count++;
printf("The value of the current term is: %f", ct);
printf("In here %d\n", count);
den = 0;
for(i = n; i > 0; i--)
{
den *= i;
}
//If the old term is one (meaning the very first term), then just set that to the current term
if (ot= 1)
{
ct = ot - (1.0/den);
}
//If n is even, add the term as per the rules of the formula
else if (n%2 == 0)
{
ct = ot + (1.0/den);
ot = ct;
}
//Else if n is odd, subtract the term as per the rules of the formula
else
{
ct = ot - (1.0/den);
ot = ct;
}
//If the current term becomes less than epsilon (the user input), printout the value and break from the loop
if (ct < epsilon)
{
printf("%f is less than %f",ct ,e);
break;
}
}
return 0;
}
Current Output
Enter a value for E: .00001
The value of e is: 0.000010
The value of the current term is: 1.000000
In here 1
-1.#INF00 is less than 0.000010
So based on everyone's comments, and using the 4th "Derangements" equation from wikipedia like I was told, this is the code I've come up with. The logic in my head seems to be in line with what everyone has been saying. But the output is not at all what I am trying to achieve. Does anyone have any idea from looking at this code what I might be doing wrong?
Σ represents a sum, so your equation means to compute the sum of the terms starting at n=0 and going towards infinity:
The notation n! means "factorial" which is a product of the numbers one through n:
Each iteration computed more accurately represents the actual value. ε is an error term meaning that the iteration is changing by less than the ε amount.
To start computing an interation you need some starting conditions:
unsigned int n = 0; // Iteration. Start with n=0;
double fact = 1; // 0! = 1. Keep running product of iteration numbers for factorial.
double sum = 0; // Starting summation. Keep a running sum of terms.
double last; // Sum of previous iteration for computing e
double e; // epsilon value for deciding when done.
Then the algorithm is straightforward:
Store the previous sum.
Compute the next sum.
Update n and compute the next factorial.
Check if the difference in the new vs. old iteration exceeds epsilon.
The code:
do {
last = sum;
sum += 1/fact;
fact *= ++n;
} while(sum-last >= e);
You need to write a beginning C program. There are lots of sources on the interwebs for that, including how to get user input from the argc and argv variables. It looks like you are to use 0.00001f for epsilon if it is not entered. (Use that to get the program working before trying to get it to accept input.)
For computing the series, you will use a loop and some variables: sum, current_term, and n. In each loop iteration, compute the current_term using n, increment n, check if the current term is less than epsilon, and if not add the current_term to the sum.
The big pitfall to avoid here is computing integer division by mistake. For example, you will want to avoid expressions like 1/n. If you are going to use such an expression, use 1.0/n instead.
Well in fact this program is very similar to the ones given in the learning to Program in C by Deitel, well now to the point (the error can't be 0 cause e is a irrational number so it can't be calculated exactly) I have here a code that may be very useful for you.
#include <stdio.h>
/* Function Prototypes*/
long double eulerCalculator( float error, signed long int *iterations );
signed long int factorial( int j );
/* The main body of the program */
int main( void )
{
/*Variable declaration*/
float error;
signed long int iterations = 1;
printf( "Max Epsilon admited: " );
scanf( "%f", &error );
printf( "\n The Euler calculated is: %f\n", eulerCalculator( error, &iterations ) );
printf( "\n The last calculated fraction is: %f\n", factorial( iterations ) );
return 1;
}
long double eulerCalculator( float error, signed long int *iterations )
{
/* We declare the variables*/
long double n, ecalc;
/* We initialize result and e constant*/
ecalc = 1;
/* While the error is higher than than the calcualted different keep the loop */
do {
n = ( ( long double ) ( 1.0 / factorial( *iterations ) ) );
ecalc += n;
++*iterations;
} while ( error < n );
return ecalc;
}
signed long int factorial( signed long int j )
{
signed long int b = j - 1;
for (; b > 1; b--){
j *= b;
}
return j;
}
That summation symbol gives you a clue: you need a loop.
What's 0!? 1, of course. So your starting value for e is 1.
Next you'll write a loop for n from 1 to some larger value (infinity might suggest a while loop) where you calculate each successive term, see if its size exceeds your epsilon, and add it to the sum for e.
When your terms get smaller than your epsilon, stop the loop.
Don't worry about user input for now. Get your function working. Hard code an epsilon and see what happens when you change it. Leave the input for the last bit.
You'll need a good factorial function. (Not true - thanks to Mat for reminding me.)
Did you ask where the constant e comes from? And the series? The series is the Taylor series expansion for the exponential function. See any intro calculus text. And the constant e is simple the exponential function with exponent 1.
I've got a nice Java version working here, but I'm going to refrain from posting it. It looks just like the C function will, so I don't want to give it away.
UPDATE: Since you've shown yours, I'll show you mine:
package cruft;
/**
* MathConstant uses infinite series to calculate constants (e.g. Euler)
* #author Michael
* #link
* #since 10/7/12 12:24 PM
*/
public class MathConstant {
public static void main(String[] args) {
double epsilon = 1.0e-25;
System.out.println(String.format("e = %40.35f", e(epsilon)));
}
// value should be 2.71828182845904523536028747135266249775724709369995
// e = 2.718281828459045
public static double e(double epsilon) {
double euler = 1.0;
double term = 1.0;
int n = 1;
while (term > epsilon) {
term /= n++;
euler += term;
}
return euler;
}
}
But if you ever need a factorial function I'd recommend a table, memoization, and the gamma function over the naive student implementation. Google for those if you don't know what those are. Good luck.
Write a MAIN function and a FUNCTION to compute the approximate sum of the below series.
(n!)/(2n+1)! (from n=1 to infinity)
Within the MAIN function:
Read a variable EPSILON of type DOUBLE (desired accuracy) from
the standard input.
EPSILON is an extremely small positive number which is less than or equal to
to 10^(-6).
EPSILON value will be passed to the FUNCTION as an argument.
Within the FUNCTION:
In a do-while loop:
Continue adding up the terms until |Sn+1 - Sn| < EPSILON.
Sn is the sum of the first n-terms.
Sn+1 is the sum of the first (n+1)-terms.
When the desired accuracy EPSILON is reached print the SUM and the number
of TERMS added to the sum.
TEST the program with different EPSILON values (from 10^(-6) to 10^(-12))
one at a time.

Resources