How to implement Trapezoidal Integration with Infinite Limits in C? - c

I am trying to create a c program to integrate sin(x)/sqrt(x) between 0 and Infinity. I am using the trapezium rule by cutting off the end points as the function tends to infinity.
However the total returned is too high and I am not sure why. Here's the code:
#include<math.h>
#include<stdio.h>
double func(double u)
{ double a;
a = ((sin(u))/(sqrt(u)));
return a;}
void main()
{
int i, N;
double sum, u, a, b, h, Fa, Fb, F;
printf("Enter value of N\n");
scanf("%d" ,&N);
a=0.01;
b=1000;
h=(b-a)/(N-1);
sum=0;
F=func(a);
u=a;
for(i=0; i<N; i++)
{
sum=sum+F;
u=u+h;
F=fabs(func(u));
}
Fa=func(a);
Fb=func(b);
sum=sum-(0.5*Fa)-(0.5*Fb);
sum=sum*h;
printf("I: %lf\n", sum);
}
Any thoughts?

working example: http://ideone.com/Xibrov
just remove the fabs in the line F=fabs(func(u));.
and you should use int main(void) and return 0; at the end instead of void main().

Your issue is on the line
F=fabs(func(u));
What you actually want for integrating func is
F=func(u);
In this case I beleive the issue is that fabs(func(u)) is not integrable at infinity, so your algorithm will diverge.

Related

Solution to heat equation

When trying to plot the solution of the heat PDE I've found some troubles. The solution that I've found is:
Here is the code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define N 10000
double f(double x);
double X[N];
double Y[N];
int main(){
int i;
double b=43351/94400;
double dx=0.0001;
X[0]=0;
Y[0]=b;
for (i=1; i<N; i++){
X[i]=X[i-1]+dx;
Y[i]=f(X[i]);
}
FILE* output;
output = fopen("dades.txt", "w");
fprintf(output, "x Posició Temperatura\n");
for (i = 0; i < N; i++){
fprintf(output, "%lf %lf %lf\n", i*dx, X[i], Y[i]);
}
fclose(output);
return 0;
}
double f(double x){
int n;
double b=43351/94400;
for (n=1; n<N; n+=2){
double pi=3.14159265358979323846;
double t0=0.025;
double result=b;
result+=2*(1-pow((-1),n))/(pi*n)*(1-exp(-pow(n,2)*pow(pi,2)*pow(t0,2)))/(pow(n,2)*pow(pi,2))*sin(n*pi*x);
}
return result;
}
What I'm trying to do is to declare a function that calculates the infinite sum for n odd, and then looping it for every x between 0 and 1. The problem is that I don't know how to declare "result" in order to be the sum of all the terms, because if I declare it outside the for loop it doesn't satisfy the boundary conditions.
(Note that I fixed t=0.025).
According to the equation, you can implement f as:
#define M_PI 3.14159265358979323846;
double f(double x)
{
int n;
double result=43351.0/94400.0;
double t0=0.025;
for (n=1; n<N; n+=2){
result+=2*(1-pow((-1),n))/(M_PI*n)*(1-exp(-pow(n,2)*pow(M_PI,2)*pow(t0,2)))/(pow(n,2)*pow(M_PI,2))*sin(n*M_PI*x);
}
return result;
}
Since you are using double, so you have to explicitly add a .0 otherwise it may be considered as integer.
The declarations of variable are moved outside the loop in order both to clarify the code and ensure the variable result gets update instead of being overwritten.
EDIT:
You could improve the function f to take the value of t as an input. This also aligns with the equation provided. It would then implements this way:
double f(double x, double t)
{
int n;
double result=43351.0/94400.0;
for (n=1; n<N; n+=2){
result+=2*(1-pow((-1),n))/(M_PI*n)*(1-exp(-pow(n,2)*pow(M_PI,2)*pow(t,2)))/(pow(n,2)*pow(M_PI,2))*sin(n*M_PI*x);
}
return result;
}
EDIT:
The implementation of the math of the equation could be further simplified:
a^2 b^2 is same as (ab)^2.
(-1)^n with n odd is always -1.
2*(1-pow((-1),n)) is a replacement for 4.
Plus, from a performance perspective you can avoid recalculation of repeated terms by putting them in a variable and the use it as you need (for instance the n^2 pi^2).

Weird bug in C: Different results to the same function sometimes right sometimes wrong

So I am trying to run this code where I calculate the mean and median in 2 functions. When I use these functions in my main function and run my program, sometimes it gives me the right answer and sometimes it gives me some random numbers for the mean even though I run the exact same code. Can somebody explain this behavior to me?
Any help is appreciated.
float mean(int *numbers, int n){
int i=0;
float solution;
float tmp_m;
for(i=0; i<n; i++){
tmp_m=(float)numbers[i]+tmp_m;
}
solution=tmp_m/((float)n);
return solution;
}
float median(int *numbers, int n){
float median;
float median_b;
int index;
int index_b;
if(n % 2 == 1){
index=n/2;
median= (float)numbers[index];
return median;
}else if (n % 2 == 0){
index_b=n/2;
float tmp_median;
tmp_median= (float)numbers[index_b] + (float)numbers[index_b-1];
median_b=tmp_median/((float)2);
return median_b;
}
}
#include <stdio.h>
int main () {
int array[6]={0,2,3,4,0,5};
int n=6;
float result=mean(array, n);
float result_median=median(array, n);
printf("%f\n%f\n", result, result_median);
return 0;
}
The variable tmp_m is left uninitialized and it gives you random values.
So, replace float tmp_m; with float tmp_m = 0; in the mean function.
You haven’t initialised tmp_m to zero before using it.
Your tmp_m is not initialized to 0, so it starts out as a random number, which results in an incorrect result

How can I convert all components of a vector into absolute value using a subprogram?

Just started learning C, and it would be great if you could help me with the following:
I just wrote a program that saves a 4-component vector entered by the user (using function called save_vector), prints it (using function called print_vector) and if any component is negative, it also prints it with all components in absolute value (positives) using the function absolute_values.
However, I am not sure how to make the function absolute_values work. The other two functions work just fine.
Looking forward to reading any suggestions to improve this piece of code! Thank you! :-)
#include <stdio.h>
void print_vector(int N,float * V);
void save_vector(int N,float * V);
void absolute_values(int N, float * V);
int main(void)
{
const int n=5;
int i;
float v[n];
puts("Enter the 5 components of the vector:");
save_vector(n, v);
puts("\nThe vector is:");
print_vector(n, v);
puts("\nThe absolute vector is:");
absolute_values(n, v);
return 0;
}
void save_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
scanf("%f",V+i);
}
void print_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
printf(" %.2f ",*(V+i));
}
void absolute_values(int N, float * V)
{
int i;
for(i=0;i<N;i++)
if (*(v+i)<0)
v[i]=v[i]*(-1);
printf(" %.2f ",*(V+i));
}
Using V instead of v. And, you miss the brace {} in for loop:
void absolute_values(int N, float * V)
{
int i;
for(i=0;i<N;i++){
if (*(V+i)<0)
V[i]=V[i]*(-1);
printf(" %.2f ",*(V+i));
}
}
You should use V[i] instead of *(V+i). Both are fine, but V[i] is easier to read the code. Do not mix them together, it makes your code difficult to read and understand.
As an alternative to the solution of #Hitokiri, I am also leaving here the function absolute_values but this time using the conditional operator. Also, following #Hitokiri's suggestion I am using V[i] as it looks cleaner.
void absolute_values(int N, float * V)
{
int i;
for(i=0;i<N;i++)
{
printf(" %.2f ", ((V[i]<0)?-V[i]:V[i]));
}
}

-1.#IND00 output for certain input values

I'm trying to write a code that will take x as input and give cos(x) as output, using maclaurin's series.I'm using a while loop until the difference of two consecutive results is less then 0.001. I'm using double type to accomodate larger values.
the code works when x is in range [-2,2], but if x is greater or less than this range the ouput is -1.#IND00. Why is it happening? is the output value out of range ? how can i fix this ??
my code is :
#include <stdio.h>
double abs(double a);
double power(double p, int q);
int fact(int a);
int main()
{
int i=1,j=2*i;
double x,s=1.0,p,l=0.001;
printf("Enter x: ");
scanf("%lf", &x);
p = s+ power(-1,i) * power(x,j) / fact(j);
while (abs(p-s)>l){
i++; j=2*i;
s=p;
p = s+ power(-1,i) * power(x,j) / fact(j);
}
printf("cos(%f) = %f", x,p);
return 0;
}
double abs(double a)
{
if (a>=0) return a;
else return (-a);
}
double power(double p, int q)
{
int i;
double a=1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
int fact(int a)
{
int i,p=1;
if (a==0 || a==1) return 1;
else
while (a!=1){
p=p*a;
a--;
}
return p;
}
update your scanf function to
scanf("%lf", &x);
Also you need to check pow and fact, these functions could overflow. Especially, fact which only use int.
As a larger |x| is use, more terms are needed and fact() overflows and strange results follow. Use double.
// int fact(int a)
double myfact(double p, int q) {
int i;
double a = 1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
Eventually with values somewhere larger |x| > 30, other limitations kick in using this method. The limitation is due to precision and not range. For large values a significantly different algorithm should be used.
Potential conflict between int abs(int j) in <stdlib.h>. The prototyped may be found via stdio.h and conflicts with OP double abs(double a). In any case, abs() is a standard library function and OP should avoid that function name. Also recommend renaming power().
// double abs(double a)
double myabs(double a)

Help implementing Least Squares algorithm in C [was: want to find the square root of an array]

the formula is pretty complicated. the numerator is num and the denominator is den, in the formula there is a root on the denominator so i have putted den in sqrrt() but sqrrt only accepts doubles
#include<stdio.h>
#include<conio.h>
#include<math.h>
#define LEN 11
// for the following set of x and y find r by the formula ..
float sum(float arr[]);
void main(void)
{ int i;
float x[]={43.22,39.87,41.85,43.23,40.06,53.29,53.29,54.14,49.12,40.71,55.15};
float y[]={102.43,100.93,97.43,97.81,98.32,98.32,100.07,97.08,91.59,94.85,94.6};
float num,den[LEN],r[LEN],xy[LEN],x2[LEN],y2[LEN];
for(i=0;i<LEN;i++)
{
x2[i]=x[i]*x[i];
y2[i]=y[i]*y[i];
xy[i]=x[i]*y[i];
}
num=sum(xy)-sum(x)*sum(y);
for(i=0;i<LEN;i++)
{
den[i]=((LEN*sum(x2)-(sum(x))*(sum(x)))*(LEN*sum(y2))-(sum(y2))*(sum(y2)));
r[i]=num /sqrt(den); /*<----------the problem is here-----> */
}
printf("%f",r);
getch();
}
float sum(float arr[])
{
int i;
float total=0;
for(i=0;i<=LEN;i++)
{
total+=arr[i];
}
return total;
}
Out of sheer boredom I have fixed your code. It is still ugly and extremely inefficient but compiles and should work. I'll leave you or someone else to make it decent.
#include <stdio.h>
#include <math.h>
#define LEN 11
// for the following set of x and y find r by the formula ..
float sum(float arr[]);
int main(void)
{ int i;
float x[]={43.22,39.87,41.85,43.23,40.06,53.29,53.29,54.14,49.12,40.71,55.15};
float y[]={102.43,100.93,97.43,97.81,98.32,98.32,100.07,97.08,91.59,94.85,94.6};
float num,den,r[LEN],xy[LEN],x2[LEN],y2[LEN];
for(i=0;i<LEN;i++)
{
x2[i]=x[i]*x[i];
y2[i]=y[i]*y[i];
xy[i]=x[i]*y[i];
}
num=LEN*sum(xy)-sum(x)*sum(y);
den = (LEN*sum(x2)) - sum(x)*sum(x);
float alpha = sum(y)/LEN - (num/den)*sum(x)/LEN;
printf("beta = %f, alpha = %f\n", num/den, alpha);
for(i=0;i<LEN;i++)
{
float term = y[i] - alpha - (num/den)*x[i];
r[i] = (term*term);
printf("%f",r[i]);
}
}
float sum(float arr[])
{
int i;
float total=0;
for(i=0;i<=LEN;i++)
{
total+=arr[i];
}
return total;
}
To be consistent with the rest of the code, you should presumably be writing:
r[i] = num / sqrt(den[i]);
However, the calculation is not one I recognize. The body of the second loop is going to produce the same result for each value in den and therefore also in r, which is probably not what the question asked for.
You need to give the index den[i] at the denominator....instead in your code you have just passed the base address!
r[i]=num /sqrt(den[i]);
If this is what you want to achieve, which is quite unclear.

Resources