In this section we discuss some methods for finding
the roots of a single variable function. That is, for the function
f(x), we
want to find the value(s) of x
where
f(x)
= 0
There is no guarantee that such a root exists for
an arbitrary function, so the code must watch or test for cases
where it doesn't.
We first look at the simplest method, Bisection,
and then look at Newton's method.
Bisection
The bisection method of root-finding only assumes
that the function is continuous. Then the existence of a root can
be determined by looking for an interval in x
over which occurs a change in sign of f(x).
When such an interval is found, we can zero in (so
to speak!) on the root by evaluating the function at the midpoint
of that interval. Whether or not the sign changes indicates which
half the root lies. We repeat this test for the interval containing
the sign change until we are within a given tolerance distance to
the zero crossing point.
The algorithm thus goes as follows:
For initial
points xl and xh, separated by a given step
size, evaluate f(xl) * f(xh) to find if
If not then
increase xl and xh by dx and test again.
When a change in sign is found, find the midpoint
and then look
for which half lies the root:
or
Repeat this
process with step size reduced to half the old value. Continue
until the function is near 0.0 within a given tolerance:
or the change
in x from one step to the next is smaller than a given tolerance
Ballistic Targets
The following program uses the bisection method to
calculate where a projectile will hit the ground. A method provides
the altitude for a body in motion in a constant gravitational field.
We put values for the constants and the initial angle into instance
variables.
Bisection_Applet5.java
(Output goes to browser's Java
console.) |
public
class
Bisection_Applet5 extends
java.applet.Applet
{
// Data for a ballistic trajectory at a given angle
double tan = Math.tan(Math.PI
/ 4.0);
double cos = Math.cos(Math.PI
/ 4.0);
double g = 9.8; // m/s^2
double v0 = 100; // m/s
public
void init()
{
double
double xl = 0.0;
double
xh = 1.0;
double
xm = 0.5;
double
step = 1.0;
double
dif = 1.0;
// Constants
double
maxSteps = 50000;
double
tol = 1.0E-2;
int
numSteps = 0;
do
{
if(
f_method(xl)
* f_method(xh)
> 0)
{
xl += step;
xh
+= step;
}
else
{
xm
= (xh+xl)/2.0;
if(
f_method(xl)
* f_method(xm)
< 0)
{
// Root on lower half
xh
= (xm+xl)/2.0;
}
else
{
// Root on upper half
xl
= xm;
xh
= (xh+xl)/2.0;
}
dif = Math.abs(f_method(xm));
step = xh-xl;
}
numSteps++;
}
while (
dif > tol && numSteps < maxSteps);
System.out.println("After
steps ="+numSteps);
System.out.println("Last
step size = "+step);
System.out.println("Root
x = "+xm+
"
within tolerance ="+dif);
}
double f_method(double
x)
{
double
val = x*tan - (0.5*g*x*x)/(v0*v0*cos*cos); ;
return
val;
}
//
Paint message in Applet window.
public void paint(java.awt.Graphics
g)
{ g.drawString("Bisection_Applet5",10,20);
}
//
Can also run this program as an application.
// No windowing needed so just run the applets
// init() function.
public static void main(String
[] args)
{
Bisection_Applet5 obj = new Bisection_Applet5();
obj.init();
}
}
|
Note: We used starter Start_Applet5.java,
which takes advantage of the trick of including the main()
method so that it can run as a standalone application or as an
applet.
The output of the above program gives
After
steps = 4082
Last step size = 0.015625
Root x = 1020.40625 within tolerance = 0.001913261718755166
|
For such problems you typically will use some prior knowledge to
guess at a inital starting value, the direction to step in, and
so forth.
Exercise: Modify the code to
try a different angle for the shot.
Latest update: Dec.15.2003
|