I have done the programming for gauss-seidel method,which is working for all inputs,except the following equation:
1.876 x1+2.985 x2-11.620 x3=-0.972
12.214 x1+2.367 x2 +3.672 x3=7.814
2.412 x1+9.879 x2 +1.564 x3 =4.890
When I am running with this input,there is a run time error of "floating point overflow."It is working fine if I am using integer input.My code is as follows:
//GAUSS SEIDEL METHOD
#include <stdio.h>
#include <conio.h>
#include <math.h>
#define e 0.001
void main() {
int i,j,n,count;
double a[10][10],x[10];
double sum,temp,error,big;
printf("Enter the number of equations: ");
scanf("%d",&n) ;
printf("Enter the co-efficients of the equations: \n");
for(i=0;i<n;i++) {
for(j=0;j<n+1;j++) {
printf("a[%d][%d]= ",i,j);
scanf("%lf",&a[i][j]);
}
}
for(i=0;i<n;i++)
x[i]=0;
count=1;
do {
big=0;
for(i=0;i<n;i++) {
sum=0;
for(j=0;j<n;j++) {
if(j!=i) {
sum = sum+a[i][j]*x[j];
}
}
temp = (a[i][n]-sum)/a[i][i];
error = fabs((x[i]-temp)/temp);
if(error>big) {
big=error;
}
x[i]=temp;
printf("%d\tx[%d] =%lf",count,i,x[i]);
}
printf("\n");
count++;
}while(big>=e);
printf("\n\nconverges to solution");
for(i=0;i<n;i++) {
printf("\nx[%d]=%lf",i,x[i]);
}
getch();
}//end
I cannot find what is to be modified.
Though it can be applied to any matrix with non-zero elements on the diagonals, convergence is only guaranteed if the matrix is either diagonally dominant, or symmetric and positive definite.
as it is stated in the wikipedia article.
Your example matrix isn't, so it mustn't come as a too big surprise that the method doesn't converge.
If you reorder the equations, move the first equation last (then the coefficient matrix becomes diagonally dominant), it quickly converges to the approximate solution
x[0]=0.500006
x[1]=0.333334
x[2]=0.250001
(the exact solution is (1/2, 1/3, 1/4)).
What happens is:
round:
first, x[0] gets a negative value (-0.972/1.876),
next, the sum for the second row becomes negative, and x[1] gets a too large value,
then, to compensate for the too large value of x[1], x[2] gets a negative value too.
round:
the sum x[1]*a[0][1] + x[2]*a[0][2] is positive, since both x[2] and a[0][2] are negative, and x[1] and a[0][1] are positive. Thus x[0] gets an even smaller negative value than in the first round,
then x[0]*a[1][0] + x[2]*a[1][2] is negative, and the value of x[1] becomes larger to compensate,
then the value of x[2] becomes a smaller negative value to compensate
and further rounds: see round 2.
After some time, you get infinities and NaNs.
Related
My professor uses this site (e-olymp.com) that automatically grades your solution in %
For this homework we have to use pointers to solve these tasks. I had a problem with this one:
The array of real numbers is given. Calculate the twice value of the minimum element in array.
Input
First line contains the number n (n ≤ 100) of elements in array. Second line contains n real numbers - the elements of array. Each value does not exceed 100 by absolute value.
Output
Print the twice value of the minimum element in array with 2 decimal digits.
My solution, works perfectly fine in compiler but gives 0%, idk where is the mistake, could you take a look at this one?
#include<stdio.h>
#include <malloc.h>
int z, x;
double fx;
int main(void){
double *c = (double *)malloc(x*sizeof(double));
scanf("%d", &x);
fx=100;
for(z=0; z<x; z++){
scanf("%lf", c+z);
if(fx>*(c+z)) fx=*(c+z);
}
printf("%.2lf", fx*2);
free(c);
return 0;
}
The natural logarithm can be approximated by the following series.
If x is input through the keyboard, write a program to calculate the
sum of first seven terms of this series.
I wrote the program as:
#include <stdio.h>
#include<math.h>
int main()
{
float x, i, sum, log_sum;
printf("Enter the value of x : ");
scanf("%f",&x);
sum=0;
for (i=2; i<=7; i++)
{
sum=sum+((1/2)*pow(((x-1)/x), i));
}
log_sum=((x-1)/x)+sum;
printf("\nSum of log series is %f\n",log_sum);
return 0;
}
The output is not matching with calculator answer. What maybe wrong here?
In the for loop you multiply everything by (1/2), given 1 and 2 are integers, the answer will be 0. Try multiplying by 0.5 instead, does that solve the problem?
I am working on the project where we are approximating e^x using a taylor series, with x being a user entered value. The test values that we have been given are x=.5, x=1.0, and x=1.5. The goal is to get the output is supposed to be a table with a row for each iteration of the loop that creates the series, with the first column containing the number of iterations, the second column the theoretical value (based on exp(x)), the third the total of the summation, and the forth difference between the theoretical value and the iterated value.
My code as it is currently is below. As it stands, my logic has some hole in it, as the code builds and runs, but the output is not correct. If I were to take a stab at my problem, i think that my summation is not starting in the right spot (1), and that the first two terms are wrong (1+x+(x^2/2!)+(x^3/3!)... etc).
What logic should I be using vs what I have? Thanks.
//cs 1325
// Dean Davis
// Dr. Paulk
// series convergence homework.
#include <stdio.h>
#include <float.h> // need it for FLT_EPSILON
#include <math.h>
unsigned long factorial(int); // function will calculate the factorial
int main()
{
int n = 0;
unsigned long fact; // this variable will hold the factorial value
float x; // this will be the value read in from the user
double theoval; // this will hold the theoretical value of e^x
double holder; // will hold the value of the nth term
double total = 0; // will accumulate the total summation
double diff; // will hold the sifferential between theoretical value and the summation
puts("Please enter a numerical value greater than zero: "); // request input
scanf_s("%f", &x); // read it in
theoval=exp(x); // calc the theoretical value
printf("# Iter e^x Sum Diff\n");
printf("------- ------- ------- -------\n"); // set up the output
while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
{
fact = factorial(n); // calls the factorial function
holder = (pow(x, n)) / fact; // calculates the term n
total = total + holder; // adds to the sum
diff = theoval - total; // calc the diff
printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
continue;
else
n++;
}
printf("The number of iterations required for convergence is: %d\n", n); // out put this line
}
unsigned long factorial(int n)
{
unsigned long int fact=n;
if (n == 0) // if n is zero, 0!=1
return 1;
else // so long as it is not, then we can calculate it like this
{
n--; // decrement it
for (n; n > 0; n--)
{
fact = fact*n; // multiply the next number by the product of all the preceding terms
}
return fact;
}
}
Your main problem is here:
if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
continue;
else
n++;
The logic is both backwards and unnecessary. It's backwards because you avoid incrementing n in exactly those cases where you want to increment it, and it's unnecessary because in the other cases you're about to exit the loop anyway because the while expression is false. Just increment n unconditionally.
This expression is also a little suspect:
(theoval - total) >= FLT_EPSILON
The macro FLT_EPSILON is related to the spacing between representable float values near 1.0. The spacing is different in different places, so it does not make sense to use it as an absolute error bound. Since the Taylor series has a well defined error bound in the form of the remainder term, I suggest instead computing the maximum possible value of the remainder term for the current n, and exiting if the ratio of that bounding error value value to the current sum is less than some reasonably small value, such as maybe 0.00001.
Besides the issue with if ((theoval - total) >= FLT_EPSILON), there's an issue with the way you're doing factorial. Those values get big quick. 13! = 6227020800 which is outside the range of a 32-bit int, so any more than 13 iterations and you get invalid results.
You don't really want to compute factorial so much as you want to compute the next term. Each term is x / n times the prior term, so you can compute each term without having to explicitly compute x^n or n!.
int n = 1; // Start at 1 with the first term included so we don't divide by 0
double holder = 1; // will hold the value of the nth term
double total = 1; // will accumulate the total summation
while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
{
holder = holder * x / n; // compute the next term from the last one
total = total + term; // adds to the sum
printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
n++;
}
I ran it, and everything seems to be fine--except that it keeps giving me a margin of error of 1. Why is it doing this?
The program is supposed to prompt the user to input an estimation for the cube root of 3, and it uses Newton's method of approximation to show how many attempts it took to get to the approximation. After 500 attempts or a margin of error less than 0.000001, it's supposed to exit the loop. Why, though, doesn't the margin of error change?
Here's my code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main()
{
float a, i, e; //declare float variables
printf("Consider the function f(x) = x^3 - 3 = 0.\n");
printf("Simplifying, we get x^3 = 3.\n");
printf("Simplifying it further, we get x = 3^(1/3).\n");
printf("Enter your estimate of the root: ");
scanf("%f", &a); //prompt user to guestimate
printf("So you're saying that x = %f.\n", a);
i=0; //initiate attempt counter
e=abs((a-pow(3, (1/3)))/pow(3, (1/3))); //margin of error formula
while (e>=0.000001 && i<=500) //initiate while loop with above expressions
{
if (a!=pow(3, (1/3)))
{
printf("Attempt %f: ", i);
a = a - (pow(a, 3) - 3)/(3*pow(a, 2));
printf("%f, ", a);
printf("%f margin of error\n", e);
i=i+1;
}
else
break;
}
}
abs() deals with ints and will return an int, you need fabsf().
In the same way, pow() is for doubles, you should use powf().
Another mistake is writing 1/3 and expecting 0.333... as a result. 1 and 3 are int literals, so the operation performed is integer division. You need to use float literals, such as 1.0f/3.0f.
That's it for type compatibility. I can see another error however : you expect e to somehow remember its formula and reapply it automagically. That's not how imperative languages work : when you write e = something, "something" is calculated and stored in e once and for all. You're doing it correctly for a, now just bring e=abs(...); inside the while loop to update it each time.
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