Free Web Site - Free Web Space and Site Hosting - Web Hosting - Internet Store and Ecommerce Solution Provider - High Speed Internet
Search the Web

Métodos Indirectos


Veremos como se implementan computacionalmente métodos para resolver la ecuación f(x) = 0 tales como el método de la Bisección, Regula false, Secante,y Newton.

Implementando una interfaz para la función

Todos los métodos iterativos , requieren una función f(x) para evaluar ciertos elementos de un intervalo. Esta función puede ser simple o una extensión de otras clases, como lo es el método evaluar(double t) de la clase Polinomio.

Para hacer flexible el uso de estas clases simples o compuestas, se declara una interfaz llamada Evaluar.

interface Evaluar
{
    double f(double x);    
}

Ejemplo de uso de la interfaz

Supongamos que vamos a buscar raíces de Polinomios de grado n. Ya que se cuenta con la clase Polinomio que permite crearlos mediante coeficientes reales, solamente tenemos que crear una clase derivada que implemente la interfaz Evaluar.

class EvalPolinomio extends Polinomio implements Evaluar
{
    public EvalPolinomio(double coef[])
    {
        super(coef);
    }
    
    public double f(double x)
    {
        return evaluar(x);     
    }
}

En la mayoría de los métodos se pasará como parámetro un objeto Evaluar, al método encargado de calcular la raíz.

La clase Biseccion, cuenta con un método llamado raiz(Evaluar e) para realizar la tarea, por lo tanto si queremos pasar un polinomio, debemos hacer lo siguiente :

/* creación de un objeto Bisección */

Biseccion b = new Biseccion( );    

/* coeficientes del polinomio (x-1)(x-2)(x+5) desarrollado */    

double coef[ ] = { 10.0 , -13.0 , 2.0 , 1.0  };

/* creación de un objeto de tipo Polinomio (extendido) */        

EvalPolinomio ep = new EvalPolinomio(coef);

/* asignación del intervalo de búsqueda */        

b.asignarDatos(0.0 , 1.8);

/* evaluación del polinimio para x = 1.5   y   x = 2.7 */        

System.out.println("f(1.5) : " + ep.f(1.5));
System.out.println("f(2.7) : " + ep.f(2.7));

/* se calcula la raíz */        
System.out.println("raiz : " + b.raiz(ep));

Ahora bien, si queremos pasar una función de prueba cualquiera, por ejemplo Exponencial de x menos x elevado a 5, declaramos una clase que implemente la interfaz correspondiente.

Ej :

class funcExp implements Evaluar
{
    public double f (double x)
    {
        return Math.exp(x) - Math.pow(x,5);     
    }
}
class pruebaExp
{
    public static void main(String arg[ ])
    {
        Biseccion b = new Biseccion();    
        
        funcExp exp = new funcExp();
        
        b.asignarDatos(0.0,2.0);
        
        System.out.println("f(0.0) : " + exp.f(0.0));
        System.out.println("f(2.0) : " + exp.f(2.0));
        
        System.out.println("raiz : " + b.raiz(exp));
    }    
}

/* salida del programa : 

   f(0.0) = 1.0
   f(2.0) = -24.61094...
   raiz : 1.295868...

*/


Método de la Bisección

Sea f : [a,b] y supongamos que f(a)* f(b) <= 0
Supongamos además que existe una única raíz t perteneciente al intervalo [a,b] tal que f(t) = 0

Algoritmo

Datos : a, b, EPSILON y f(x)

Paso 1) c = ( a + b ) / 2

Paso 2) SI ( b - c <= EPSILON ) ENTONCES
              raiz = c   y  fin
           SINO
               seguir

Paso 3) SI ( f(a) * f(c) <= 0)
               b = c
           SINO
               a = c

Paso 4) Volver a paso 1

Implementación

La clase Bisección consta de tres métodos encargados de asignar el intervalo de búsqueda (asignarDatos), retornar el número de iteraciones necesarias para encontrar la raíz (numIteraciones) y finalmente el método que aplica el algoritmo de la bisección (raiz).

Para evitar un loop infinito, se incluye una constante que restringe el número máximo de iteraciones que debieramos esperar (MAX_ITER).

class Biseccion 
{
    public static double EPSILON = 0.00005;
    public final static int MAX_ITER = 500; 
    
    private double a,b,c;
    
    private int cont;
    
    public void asignarDatos(double a , double b)
    {
        this.a = a;
        this.b = b;
        this.cont = 0;
    }
    
    public int numIteraciones( )
    {
        return cont;    
    }
    
    public double raiz( Evaluar e )
    {
        while(true)
        {
            c = (a + b) / 2;
            
            if( b - c <= EPSILON) break;    

            if ( f(a) * f(c) <= 0.0)
                b = c;
            else
                a = c;
        
            cont++;
            if (cont > MAX_ITER ) break;
        }    
        
        return c;
    } 
}

Programa de prueba

Se va a encontrar las raíces del polinomio : (x-3)(x+2)(x-1) mediante el método de la bisección , además de realizar la evaluación del intervalo de búsqueda y mostrar el número de iteraciones que se realizó en la búsqueda.

Código fuente

class pruebaBisecc
{
    public static void impResult(double a , double b , Biseccion bisecc , Evaluar e)
    {
        bisecc.asignarDatos(a,b);
        
        System.out.println("\n\tEvaluacion de intervalo : [ " + a + " , " + b + " ]\n");
        System.out.println("\tf(" + a + ") : " + e.f(a));
        System.out.println("\tf(" + b + ") : " + e.f(b));
        
        System.out.println("\traiz : " + bisecc.raiz(e));
        System.out.println("\tNumero de iteraciones : " + bisecc.numIteraciones());    
    }
    
    public static void main(String arg[ ])
    {
        Biseccion b = new Biseccion( );    
        
        /*  polinomio : (x-3)(x+2)(x-1) = 6 - 5x - 2x^2 + x^3 */
        double coef[ ] = { 6.0 , -5.0 , -2.0 , 1.0  };
        
        EvalPolinomio ep = new EvalPolinomio(coef);
        
        System.out.println("\n\tPolinomio : " + ep.toString("x"));
        
        impResult(1.8 , 3.9 , b , ep);
        impResult(-3.3 , -1.0 , b , ep);
        impResult(-0.2 , 1.6 , b , ep);
    
        System.out.println( );
    }    
}
bajar archivos
siguiente