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.
Related
This is my homework:
I haven't tried to write the part of Natural Logarithm because I can't solve the part of Exponential.
This is the the approximations of Exponential in C using Taylor Series expansion I wrote.
However, it returns inf. What did I do wrong?
#include <stdio.h>
// Returns approximate value of e^x
// using sum of first n terms of Taylor Series
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int a = n; a >= 0; ++a ) {
while (x * sum / a < 0.00001) {
break;
}
sum = 1 + x * sum / a;
return sum;
}
}
int main()
{
int n = 0;
float x = 1.0f;
printf("e^x = %.5f", exponential(n, x));
return 0;
}
With How do I ask and answer homework questions? in mind, I will give you a few things to have a careful look at.
From comment by Spektre:
from a quick look you are dividing by zero in while (x * sum / a < 0.00001) during first iteration of for loop as a=n and you called the function with n=0 ... also your code does not match the expansion for e^x at all
Have a look at the for loop:
for (int a = n; a >= 0; ++a )
What is the first value of a? The second? The third?
Keep in mind that the values are determined by ++a.
When will that loop end? It is determined by a >= 0. When is that false?
What is this loop doing?
while (x * sum / a < 0.00001) {
break;
}
I suspect that you programmed "English to C", as "do the outer loop while ...", which is practically from the assignment.
But the loop does something else. Apart from risking the division by 0 mentioned above, if the condition is true it will stay true and cause an endless loop, which then however is immediatly canceled in the first iteration.
The head of your function float exponential(int n, float x) expects n as a parameter. In main you init it with 0. I suspect you are unclear about where that value n is supposed to come from. In fact it is unknown. It is more a result of the calculation than an input.
You are supposed to add up until something happens.
You do not actually ever need the value of n. This means that your for loop is meaningless. The inner loop (though currently pointless) is much closer to your goal.
I will leave it at this for now. Try to use this input.
Feel free to edit the code in your question with improvements.
(Normally that is not appreciated, but in case of homework dialog questions I am fine with it.)
Your current implementation attempt is quite a bit off. Therefore I will describe how you should approach calculating such a series as given in your quesiton.
Let's look at your first formula:
You need to sum up terms e(n) = x^n / n!
To check with your series: 1 == x^0 / 0! - x == x^1 / 1! - ...
To calculate these terms, you need a simple rule how to get from e(n) to e(n+1). Looking at the formula above we see that you can use this rule:
e(n+1) = e(n) * x / (n+1)
Then you need to create a loop around that and sum up all the bits & pieces.
You are clearly not supposed to calculate x^n/n! from scratch in each iteration.
Your condition to stop the loop is when you reach the limit of 1e-5. The limit is for the new e(n+1), not for the sum.
For the other formulas you can use the same approach to find a rule how to calculate the single terms.
You might need to multiply the value by -1 in each step or do something like *x*n/(n+1) instead of *x/(n+1) etc.
Maybe you need to add some check if the formula is supposed to converge. Then maybe print some error message. This part is not clear in your question.
As this is homework, I only point into the direction and leave the implementation work to you.
If you have problems with implementation, I suggest to create a new question.
#include <stdio.h>
int main() {
float power;
printf("Enter the power of e\n");
scanf("%f", &power);
float ans = 1;
float temp = 1;
int i = 1;
while ((temp * power) / i >= 0.00001) {
temp = (temp * power) / i;
ans = ans + temp;
i++;
}
printf("%.5f", ans);
return 0;
}
I think I solved the problem
But the part about Natural Log is not solved, I will try.
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.
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.
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.
Am creating a program in c which is suppose to estimate the root of a 10 order polynomial using newton raphson method. The user enters 10 coefficients and it is suppose to estimate the root of the equation. the absolute relative error is 0.00000001 and maximum number of iterations allowed are 70. sample code is below.
n=0;
while(abserr<=0.00000001){
yold=y;
y = y-(poly(y,coefficients,11)/poly_der(y,coefficients,11));
ynew = y;
error=ynew-yold;
abserr=sqrt(error*error);
printf("iteration x%d = %.2f error =%.2f\n",n+1,y,abserr);
n++;
iteration++;
if(iteration==70){
printf("you have reached the maximum number of iterations\n");
break;}
}
the functions poly and poly_der calculate the value of the polynomial and its derivative respectively. there defnitions are below.
float poly(float x, float coefficients[], int order)
{
int idx;
float total;
for (idx = 0; idx < order; idx++)
total += coefficients[idx] * pow(x, idx);
return total;
}
float poly_der(float x, float coefficients[], int order)
{
int idx;
float total;
for (idx = 0; idx < order; idx++)
total += coefficients[idx] * deri(x, idx);
return total;
}
deri is function which calculates the derivative of a term in the polynomial.
Unfortunately this program produces unexpected results. i cant figure out where am wrong because it compiles and runs fine. Is there another way i can estimate the root using newton's method. How can i improve the program so it produces the required results.
You have several unitialized variables: total (twice) and seemingly iteration as well. If you don't initialize a variable, its value is undefined and may even differ between runs of the same program.
Do total = 0. before entering the loop in poly and poly_der.
Here are some things that might help:
Post the function.
Post what you expect the root to be.
Post the result you got, along with the inputs that you provided.
Give some idea of what starting conditions you chose, because iterative methods like N-R can give different results depending on where you start.
Tell us why you're certain it's not a local minimum that N-R gave you.
What's that deri() function? Is that yours?