Integrating via trapezium rule in C - c

I'm trying to integrate the function 1/((1+x^2)x^0.5) between 0 and infinity using the trapezium rule.
I need to find the value of N that gives the highest precision possible when using a double float, which I have done by running the program with increasing values of N until there is no difference between the totals given by consecutive values of N. However I am stuck in an infinite loop.
Thanks
Beth
#include<stdio.h>
#include<math.h>
#include<float.h>
double inter(double x, double h, double y, double N, double total)
{
h=(y-x)/(N-1);
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("t - %lf \n", total);
//printf("x - %lf \n", x);
}
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
total=total*h;
return total;
}
main()
{
double x,y,total,h,c,d,f,N, finish;
x=DBL_EPSILON;
y=331;
total=0;
N=0.5;
c=inter(x,h,y,N,total);
d=0;
finish=0;
while(finish==0)
{
d=inter(x,h,y,N,total);
if(d==c)
{
finish=1;
}
else
{
c=d;
d=0;
h++;
printf("%lf/n", h);
}
}
printf("%lf\n", d);
}

In your iter() function, h is negative, which causes x to go negative. sqrt() of a negative number returns NaN. Additionally, because h is negative, x continues to get smaller, thus is always being smaller than y, which is the cause of the infinite loop.
h is negative because the denominator (N-1) comes out to -0.5 (N is passed in as 0.5).

double h has not been initialised. You are passing it as a function argument, which then overwrites it to use as a local variable. However, in the main loop you increment h (using the ++ operator which would be better as h+=1) and then pass it to the function again, but it has no effect, as h is still over written in the function.
As a point of technique, you are using double finish as a boolean. It should be int finish.

Related

Riemann Sum, Trapezoidal rule in C

I've been trying to write a program that solves the area under a curve in C by using the Trapezoidal rule. The problem is, I think my logic is ok, I've review many times the algorithm and I can't still find the error.
In this was something assigned by my professor and he doesn't want us to use array, that's why you won't see any.
It scans func,a, p, q, err, where func is the function that will be used(function #1 or #2, but I've only done the #1),a is a constant, p is the initial x, q is the final x, and err is the margin of error, I think.
the program will divide the interval and calculate areas until last calculation of Area - total area we just calculates equals less than 10^-err
EDIT:I've made a few changes thanks to LutzL
#include<stdio.h>
#include<math.h>
double F1(double x,double a){
double f1=0.0;
f1=(sqrt(a-pow(x,2)));
return f1;
}
int main(){
double a=0.0,p=0.0,q=0.0,h=0.0,x=0.0,err=0;
int func=3,n=2;
double power=0.0,T=0.0;
double sum=0.0,last=0.0,difference=1.0;
scanf("%d",&func);
while(func!=0){
n=2;
scanf("%lf%lf%lf%lf",&a,&p,&q,&err);
power=pow(10.0,-err);
h=(q-p)/n;
if(func==1){
difference=1.0;
while(difference>=power){
h=(q-p)/n;
sum=0.0;
for(x=p+h;x<=q-h;x++){
sum+=(2*F1(x,a));
}
T=(h/2)*(F1(p,a)+F1(q,a)+sum);
if(difference==1.0){
difference=T;
}else{
difference=last-T;
}
last=T;
n++;
}
}
printf("%.5lf\n",T);
scanf("%d",&func);
}
return 0;
}
The error is when I input 1, 4, -2, 1, 9. It should output 5.05481, but instead, it outputs 4.59808.
sum should add the function values for the arguments from p+h to p+(n-1)*h=q-h, that is, n-1 function values. At the moment you add n function values.
You do not double n inside the loop.
The best implementation uses midpoint sums
M(k)= f(p+h/2)+f(p+3h/2)+...+f(p+(2n-1)*h/2)
where n=2^k, h=(q-p)/2^k.
Then the trapezoidal sums
T(k)=0.5*f(p)+f(p+h)+...+f(p+(n-1)*h)+0.5*f(q)
satisfy the recursion
T(k+1) = T(k) + M(k)
with T(0)=(f(p)+f(q))/2. The integral approximations are of course T(k)*(q-p)/2^k.

Example of a colloquium exam

Check the image
This is my 1st post so have that in mind while reading my question.
I have an exam of a colloquium but my code does not provide me the correct result.
So if anyone could help me that would be great. :)
These are the informations that are provided in the exam:
A function y=f(x)=ax^2+bx+c
We have to find the surface that is below the chart but keep in mind that dx(Delta X)=B-A and the height goes like this: A,A+dx,A+2dx, .... , B-dx.
As dx value gets lower the surface will be more accurate.
You have to write the program so that the surface with precision 0.001
This is my code so could someone who is good in C check it please.
Thank you.
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c;
double A,B,dx,p,D,q,x,y,nv,nv1,nv2,sv;
do{
printf("Insert a & b: "),scanf("%lf %lf",&A,&B);
} while(A<1 || B<1);
nv=dx=B-A;
do{
printf("enter odds: "),scanf("%d %d %d",&a,&b,&c);
p=(-b)/2;
D=sqrt(pow(b,2)-4*a*c);
q= -D/4*a;
} while( a<0 || p<0 || q<0);
do{
sv=nv;
dx/=2;
nv=0;
for(x=A;x<p;x+=dx)
for(dx=B-A;dx<q;dx/=2)
nv1+=x*dx;
for(y=p;y<=B;y+=dx)
for(dx=q;dx<B;dx/=2)
nv2+=y*dx;
nv=nv1+nv2;
}while(fabs(nv-sv)>0.001);
printf("The surface is %lf",nv);
return 0;
}
You want to find the approximation of a definite integral of a quadratic function. There are several issues with your code:
What is the restriction of A ≥ 1 and B ≥ 1 for? A parabola is defined over the whole abscissa. If anything, you should enforce that the input is numeric and that two values were given.
You don't need to find the vertex of the parabola. Your task is to create small rectangles based on the left x value of each interval as the image shows. Therefore, you don't need p and q. And you shouldn't enforce that the vertex is in the first quadrant on the input without indication.
Why are the coefficients of the parabola integers? Make them doubles to be consistent.
Because you don't need to know the vertex, you don't need to split your loop in two. In your code, you don't even check that p is between A and B, which is a requirement of cour code.
What is the inner loop for? You are supposed to just calculate the area of the current rectangle here. What's worse: you re-use the variable dx as iteration variable, which means you lose it as an indicator of how large your current interval is.
The repeated incrementing of dx may lead to an accumulated floating-point error when the number of intervals is large. A common technique to avoid this is to use an integer variable for loop control and the determine the actual floating-point variable by multiplication.
The absolute value as a convergence criterion may lead to problems with small and big numbers. The iteration ends too early for small values and it may never reach the criterion for big numbers, where a difference of 0.001 cannot be resolved.
Here's a version of your code that puts all that into practice:
#include <stdio.h>
#include <math.h>
int main()
{
double a, b, c;
double A, B;
printf("Lower and upper limit A, B: ");
scanf("%lf %lf", &A, &B);
printf("enter coefficients a, b, c: ");
scanf("%lf %lf %lf", &a, &b, &c);
double nv = 0;
double sv;
int n = 1;
do {
int i;
double dx;
sv = nv;
n *= 2;
dx = (B - A) / n;
nv = 0;
for (i = 0; i < n; i++) {
double x = A + i * (B - A) / n;
double y = a*x*x + b*x + c;
nv += dx * y;
}
} while(fabs(nv - sv) > 0.0005 * fabs(nv + sv));
printf("Surface: %lf\n", nv);
return 0;
}
The code is well-behaved for empty intervals (where A = B) or reversed intervals (where A > B). The inpt is still quick and dirty. It should really heck that the entered values are valid numbers. There's no need to restrict the input arbitrarily, though.

Regula-Falsi Algorithm?

I'm trying to implement the Regula-Falsi Algorithm to solve the equation of 2(x^3)-x-2
but the problem is that the variable c value is staying constant and it is not changing, even that my code should change it .
#include<math.h>
#include<stdio.h>
float fonc(float x)
{
int result;
result=2*(pow(x,3))-x-2;
return result;
}
int main(void)
{
float eps=pow(10,-4);
int i=0;
float a,b,c;
a=1;
b=2;
do
{
c=((a*fonc(b))-(b*fonc(a)))/((fonc(b)-fonc(a)));
if(fonc(c)*fonc(a)<0)
{
b=c;
}
else
{
a=c;
}
i++;
printf("\n%f",c);
}
while(fabs(b-c)>eps);
printf("le nombre d'itération %d",i);
}
What can go wrong with the algorithm as presented, even if all data types were appropriate?
In contrast to the bisection method, the pure regula falsi will not force the interval length to go to zero. If a monotone and convex function is used, the iteration will stall at changing only one side of the interval with geometric convergence. Any sufficiently smooth function will eventually have these properties over the remaining bracketing interval.
To correctly catch this behavior, the midpoint c should be compared to both interval ends a, b immediately after computation. As bonus point, check if the value at c is small enough and if true, also break the iteration regardless of how far from the ends of the interval this is.
There exist many simple tricks to force the interval length to be zero. The complicated tricks lead to the Brent's method. Of simple tricks one is the Illinois variant. In these variants, the midpoint is considered as a convex sum
c = |f(b)|/(|f(a)|+|f(b)|) * a + |f(a)|/(|f(a)|+|f(b)|) * b
Because of the opposite signs of f(a) and f(b), this is equivalent to the original formula. If the side b does not change, its importance in this convex sum is increased by decreasing the function value f(b), i.e., multiplying it with additional weight factors. This moves the midpoint c towards b, which will in very few steps find a midpoint that will replace b.
The following is an implementation of the Illinois variant of regula falsi (or false position method). The algorithm finds a solution with function value 2.2e-6 and an enclosing interval of length 6e-7 in 6 iterations.
#include<math.h>
#include<stdio.h>
float fonc(float x)
{
return (2*x*x-1)*x-2;
}
int main(void)
{
float eps=1e-6;
int i=0;
float a=1, fa = fonc(a);
float b=2, fb = fonc(b);
printf("\na=%10.7f b=%10.7f fa=%10.7f fb=%10.7f\n------\n",a,b, fa,fb);
if(signbit(fb)==signbit(fa)) {
printf("Attention, les valeurs initiales de 'fonc' n'ont pas de signe opposeés!\n");
}
do
{
float c=(a*fb-b*fa)/(fb-fa), fc = fonc(c);
if( signbit(fc)!=signbit(fa) )
{
b=a; fb=fa;
}
else
{
fb *= 0.5;
}
a=c; fa=fc;
i++;
printf("\na=c=%10.7f b=%10.7f fa=fc=%10.7f fb=%10.7f",c,b, fc,fb);
if(fabs(fc)<eps) break;
}
while(fabs(b-a)>eps);
printf("\nle nombre d'itération %d\n",i);
return 0;
}
The output is
a= 1.0000000 b= 2.0000000 fa=-1.0000000 fb=12.0000000
------
a=c= 1.0769231 b= 2.0000000 fa=fc=-0.5789710 fb= 6.0000000
a=c= 1.1581569 b= 2.0000000 fa=fc=-0.0512219 fb= 3.0000000
a=c= 1.1722891 b= 1.1581569 fa=fc= 0.0497752 fb=-0.0512219
a=c= 1.1653242 b= 1.1722891 fa=fc=-0.0003491 fb= 0.0497752
a=c= 1.1653727 b= 1.1722891 fa=fc=-0.0000022 fb= 0.0248876
a=c= 1.1653733 b= 1.1653727 fa=fc= 0.0000020 fb=-0.0000022
le nombre d'itération 6
Okay, just for the sake of correcting the algorithm to actually perform what it was meant to perform:
Along with changing the type of result from int to float, you also need to change the loop condition. Currently it is:
while ( fabs( b - c ) > eps );
Which means that the loop will continue happening until the distance between the values b and c become lower than 0.0001, and under this condition, currently, at least on my end, the code runs forever.
We aren't after reducing the difference between b and c anyway. What we really are after is that the fonc( c ) = 2*c*c*c - c - 2 to be less than our eps. In the end, we want it to be as close as possible to zero, so that c becomes approximately a root of the function. So simply:
while ( fabs( fonc( c ) ) > eps );
is what our condition should be. This way, along with the int --> float change, it doesn't fall into an infinite loop, completing the job in 14 iterations.
One problem is that result is int. You almost certainly want to be float or double, as otherwise the result of fonc() is getting truncated to an integer.

Getting nan as the accumulated sum

I have a code for doing integrations and in the last for loop starting on line 67 I have a for loop which accumulates the values of the function at randomly generated points to get the integral(Monte Carlo integration). Unfortunately after the loop finishes I get NAN as the result for "monte2" variable. I have written a printf statement inside the for loop to pinpoint the mistake only to notice that after 235.494781 the sum turns into -nan. What may be the reason behind this problem? I am running Ubuntu 12.04.3 LTS 32-bit and compile the plain C code with GCC version 4.6.3. I appreciate your help, the code is as follows:
P.S: The code is originally written in Code Blocks on Windows 8 64-bit by a friend of mine if this makes a difference.
#include<stdio.h>
#include<math.h>
float I1(float x)
{
return exp(-x)*cos(x*x)*cos(x*x);
}
float I2(float t)
{
return cos(log(t)*log(t))*cos(log(t)*log(t));
}
float random()
{
float a;
a=rand()%1000;
a=a/1000*20;
// printf("%.15f\t%f\n",I1(a),a);
return a;
}
float random2()
{
float a;
a=rand()%1000;
a/=1000;
// printf("%.15f\t%f\n",I2(a),a);
return a;
}
int main()
{
FILE *data=fopen("data.txt","w");
FILE *data2=fopen("data2.txt","w");
float trap=0,monte=0,sum=0, monte2=0;
float a[1000],b[1000],dt=0.005;
int i;
/* Part 1 */
for(i=0;i<1000;i++)
a[i]=I1(i*dt);
for(i=0;i<1000;i++)
fprintf(data,"%f\t%f\n",i*dt,a[i]);
for(i=1;i<1000;i++)
trap+=(a[i]+a[i-1])/2*dt;
printf("The integral value of I1 is = %f with trapezoid rule\n",trap);
for(i=0;i<500;i++)
monte+=I1(random());
printf("The Monte Carlo Technique value for I1 is %f with 500 samples\n",monte/500*20);
/* Part 2 */
dt=0.001;
printf(" \n");
for(i=1;i<=1000;i++)
b[i]=I2(i*dt);
for(i=1;i<=1000;i++)
fprintf(data2,"%f\t%f\n",i*dt,b[i]);
for(i=2;i<=1000;i++)
trap+=(b[i]+b[i-1])/2*dt;
printf("The integral value of I2 is = %f with trapezoid rule\n",trap/2);
for(i=0;i<500;i++)
{
monte2+=I2(random2());
printf("%f \n", monte2);
}
printf("The Monte Carlo Technique value of I2 is %f with 500 samples\n",monte2/500);
printf("\n");
printf("Comment 1: Two values obtained with trapezoid rule is close to each other;however,they are not exactly same.\n");
printf("\n");
printf("Comment 2: The integral value and monte carlo value of I1 is closer than the integral value and monte carlo value of I2.This means that we have better expectation value of I1 with monte carlo technique with 500 samples.\n");
fclose(data2);
fclose(data);
return 0;
}
Your function call
monte2+=I2(random2());
may produce NaN. This is because random2 may returns 0. log 0 is infinity. This will cause cos(log(t)*log(t))*cos(log(t)*log(t)) to produce NaN.
See the graph for log function:
Note that the graph gets arbitrarily close to the y axis, but does not meet or intersect it1.
1. Source Wikipedia

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