public class MyFunction { public static double f(double x) // Sample function { return (x * x - 3); // x^{2} - 3 } } |
public class TestProg { public static void main(String[] args) { double x; for ( x = 0.0; x < 10.5; x++ ) System.out.println("x = " + x + ", f(x) = " + MyFunction.f(x) ); } } |
(NOTE: from calculus, because f(x) has opposite signs for x = a and x = b and f(x) is continuous, we know there is a zero in (a, b) !)
This technique is called the bisection technique
The bisection technique
a = left point of interval b = right point of interval while ( width of the interval > ε ) { m = (a + b)/2.0; // midpoint of interval if ( f(m) has the same sign as f(b) ) { b = m; // Next search interval is ( a, (a+b)/2 ) } else { a = m; // Next search interval is ( (a+b)/2, b ) } } |
We can clearly see that the zero in this case must be in the interval ( a, (a+b)/2 )
By setting:
b = m;We change the search interval to (a, m) or (a, (a+b)/2) in the next iteration.
We can clearly see that the zero in this case must be in the interval ( (a+b)/2, b )
By setting:
a = m;We change the search interval to (a, m) or ((a+b)/2, b) in the next iteration.
public class MathToolBox { public static double solveEquation(double a, double b) { double leftPoint, rightPoint, midPoint; // Interval points double y_leftPoint, y_rightPoint, y_midPoint; // Function values /* ------------------------------------------------------ Sanity check 1: b > a ------------------------------------------------------ */ if ( b < a ) { System.out.println("Error: illegal interval "); return(0); // We need to return something.... } /* ------------------------------------------------------ Sanity check 2: sign f(a) and f(b) must be different ------------------------------------------------------ */ if ( (MyFunction.f(a) > 0 && MyFunction.f(b) > 0) || (MyFunction.f(a) < 0 && MyFunction.f(b) < 0) ) { System.out.println("Error: interval may not contain a zero"); return(0); // We need to return something.... } /* --------------------------------------------------- The Bisection Algorithm --------------------------------------------------- */ leftPoint = a; // Initial interval is (a, b) rightPoint = b; while ( rightPoint - leftPoint > EPSILON ) // See note { midPoint = (leftPoint + rightPoint)/2.0; // Find the middle y_midPoint = MyFunction.f(midPoint); y_rightPoint = MyFunction.f(rightPoint); if ( (y_midPoint < 0 && y_rightPoint < 0) || (y_midPoint > 0 && y_rightPoint > 0) ) { rightPoint = midPoint; } else { leftPoint = midPoint; } } return (leftPoint + rightPoint)/2.0; } public static final double EPSILON = 0.000001; // Minimum accuracy } |
If the interval width is less that EPSILON, then the error of the solution cannot be more than EPSILON !
What does it mean for "rightPoint - leftPoint < EPSILON": |<------ < EPSILON ----->| -------+-------------------------+------- leftPoint rightPoint An example will make it clear: take EPSILON = 0.001 -------+-------------------------+------- leftPoint = 3.145 rightPoint = 3.146 Then 3.1455 is a good approximation of the solution
NOTE: from calculus, this problem is also known as the definite integral:
This technique is called the rectangle method:
The following diagram shows use what (i.e., the steps) exactly is repeated:
Repeat these steps for each sub-interval (x_{i}, x_{i+1}):
So we can move (x_{i+1} - x_{i}) outside the summation.
So each sub-interval has a length of (b - a)/n !!!
(in other words, rectangleRule() is called as rectangleRule(a, b, n) where a and b are 2 double values and n is an integer)
public class MathToolBox { public static double rectangleRule(double a, double b, int n) { double h; // Length of each sub-interval double x_i; int i; double integral; /* --------------------------------------------------- Sanity check: b > a --------------------------------------------------- */ if ( b < a ) { System.out.println("Error: illegal interval "); return(0); // We need to return something.... } /* --------------------------------------------------- The Rectangle Rule Algorithm --------------------------------------------------- */ h = (b-a)/n; integral = 0.0; x_i = a; // First sub-interval point for ( i = 1; i <= n; i++ ) { integral = integral + MyFunction.f(x_i) * h; // ^^^^^^^^^^^^^^^^^^^^^ Area of rectangle x_i = x_i + h; } return ( integral ); } /** * (NO CHANGES MADE TO solveEquation() !!!! */ public static double solveEquation(double a, double b, int n) { .... (unchanged !!) } public static final double EPSILON = 0.000001; // Minimum accuracy } |