Equation Solving
Linear Equation
There are two classes of methods for solving Linear Equations:
-
Direct Methods: Common characteristics of direct methods are that they transform the original equation into equivalent equations that can be solved more easily, means we get solve directly from an equation.
-
Iterative Method: Iterative or Indirect Methods, start with a guess of the solution and then repeatedly refine the solution until a certain convergence criterion is reached. Iterative methods are generally less efficient than direct methods because large number of operations required. Example- Jacobi’s Iteration Method, Gauss-Seidal Iteration Method.
Implementation in C-
//Implementation of Jacobi's Method
void JacobisMethod(int n, double x[n], double b[n], double a[n][n]){
double Nx[n]; //modified form of variables
int rootFound=0; //flag
int i, j;
while(!rootFound){
for(i=0; i<n; i++){ //calculation
Nx[i]=b[i];
for(j=0; j<n; j++){
if(i!=j) Nx[i] = Nx[i]-a[i][j]*x[j];
}
Nx[i] = Nx[i] / a[i][i];
}
rootFound=1; //verification
for(i=0; i<n; i++){
if(!( (Nx[i]-x[i])/x[i] > -0.000001 && (Nx[i]-x[i])/x[i] < 0.000001 )){
rootFound=0;
break;
}
}
for(i=0; i<n; i++){ //evaluation
x[i]=Nx[i];
}
}
return ;
}
//Implementation of Gauss-Seidal Method
void GaussSeidalMethod(int n, double x[n], double b[n], double a[n][n]){
double Nx[n]; //modified form of variables
int rootFound=0; //flag
int i, j;
for(i=0; i<n; i++){ //initialization
Nx[i]=x[i];
}
while(!rootFound){
for(i=0; i<n; i++){ //calculation
Nx[i]=b[i];
for(j=0; j<n; j++){
if(i!=j) Nx[i] = Nx[i]-a[i][j]*Nx[j];
}
Nx[i] = Nx[i] / a[i][i];
}
rootFound=1; //verification
for(i=0; i<n; i++){
if(!( (Nx[i]-x[i])/x[i] > -0.000001 && (Nx[i]-x[i])/x[i] < 0.000001 )){
rootFound=0;
break;
}
}
for(i=0; i<n; i++){ //evaluation
x[i]=Nx[i];
}
}
return ;
}
//Print array with comma separation
void print(int n, double x[n]){
int i;
for(i=0; i<n; i++){
printf("%lf, ", x[i]);
}
printf("\n\n");
return ;
}
int main(){
//equation initialization
int n=3; //number of variables
double x[n]; //variables
double b[n], //constants
a[n][n]; //arguments
//assign values
a[0][0]=8; a[0][1]=2; a[0][2]=-2; b[0]=8; //8x₁+2x₂-2x₃+8=0
a[1][0]=1; a[1][1]=-8; a[1][2]=3; b[1]=-4; //x₁-8x₂+3x₃-4=0
a[2][0]=2; a[2][1]=1; a[2][2]=9; b[2]=12; //2x₁+x₂+9x₃+12=0
int i;
for(i=0; i<n; i++){ //initialization
x[i]=0;
}
JacobisMethod(n, x, b, a);
print(n, x);
for(i=0; i<n; i++){ //initialization
x[i]=0;
}
GaussSeidalMethod(n, x, b, a);
print(n, x);
return 0;
}
Non-Linear Equation
An equation of the type f(x)=0
is either algebraic or transcendental. These types of equations can be solved by using two types of methods-
-
Direct Method: This method gives the exact value of all the roots directly in a finite number of steps.
-
Indirect or Iterative Method: Iterative methods are best suited for computer programs to solve an equation. It is based on the concept of successive approximation. In Iterative Method there are two ways to solve an equation-
-
Bracketing Method: We take two initial points where the root lies in between them. Example- Bisection Method, False Position Method.
-
Open End Method: We take one or two initial values where the root may be any-where. Example- Newton-Raphson Method, Successive Approximation Method, Secant Method.
-
Implementation in C-
/// Here define different functions to work with
#define f(x) ( ((x)*(x)*(x)) - (x) - 2 )
#define f2(x) ( (3*(x)*(x)) - 1 )
#define g(x) ( cbrt( (x) + 2 ) )
/**
* Takes two initial values and shortens the distance by both side.
**/
double BisectionMethod(){
double root=0;
double a=1, b=2;
double c=0;
int loopCounter=0;
if(f(a)*f(b) < 0){
while(1){
loopCounter++;
c=(a+b)/2;
if(f(c)<0.00001 && f(c)>-0.00001){
root=c;
break;
}
if((f(a))*(f(c)) < 0){
b=c;
}else{
a=c;
}
}
}
printf("It took %d loops.\n", loopCounter);
return root;
}
/**
* Takes two initial values and shortens the distance by single side.
**/
double FalsePosition(){
double root=0;
double a=1, b=2;
double c=0;
int loopCounter=0;
if(f(a)*f(b) < 0){
while(1){
loopCounter++;
c=(a*f(b) - b*f(a)) / (f(b) - f(a));
/*/printf("%lf\t %lf \n", c, f(c));/**////test
if(f(c)<0.00001 && f(c)>-0.00001){
root=c;
break;
}
if((f(a))*(f(c)) < 0){
b=c;
}else{
a=c;
}
}
}
printf("It took %d loops.\n", loopCounter);
return root;
}
/**
* Uses one initial value and gradually takes that value near to the real one.
**/
double NewtonRaphson(){
double root=0;
double x1=1;
double x2=0;
int loopCounter=0;
while(1){
loopCounter++;
x2 = x1 - (f(x1)/f2(x1));
/*/printf("%lf \t %lf \n", x2, f(x2));/**////test
if(f(x2)<0.00001 && f(x2)>-0.00001){
root=x2;
break;
}
x1=x2;
}
printf("It took %d loops.\n", loopCounter);
return root;
}
/**
* Uses one initial value and gradually takes that value near to the real one.
**/
double FixedPoint(){
double root=0;
double x=1;
int loopCounter=0;
while(1){
loopCounter++;
if( (x-g(x)) <0.00001 && (x-g(x)) >-0.00001){
root = x;
break;
}
/*/printf("%lf \t %lf \n", g(x), x-(g(x)));/**////test
x=g(x);
}
printf("It took %d loops.\n", loopCounter);
return root;
}
/**
* uses two initial values & both value approaches to the root.
**/
double Secant(){
double root=0;
double x0=1;
double x1=2;
double x2=0;
int loopCounter=0;
while(1){
loopCounter++;
/*/printf("%lf \t %lf \t %lf \n", x0, x1, f(x1));/**////test
if(f(x1)<0.00001 && f(x1)>-0.00001){
root=x1;
break;
}
x2 = ((x0*f(x1))-(x1*f(x0))) / (f(x1)-f(x0));
x0=x1;
x1=x2;
}
printf("It took %d loops.\n", loopCounter);
return root;
}
int main(){
double root;
root = BisectionMethod();
printf("Using Bisection Method the root is: %lf \n\n", root);
root = FalsePosition();
printf("Using False Position Method the root is: %lf \n\n", root);
root = NewtonRaphson();
printf("Using Newton-Raphson Method the root is: %lf \n\n", root);
root = FixedPoint();
printf("Using Fixed Point Method the root is: %lf \n\n", root);
root = Secant();
printf("Using Secant Method the root is: %lf \n\n", root);
return 0;
}