Métodos Numéricos con JAVA
Thursday, 3 de May de 2007
-
Introducción
EL Java es el lenguaje para el Internet, y entre sus características esta que es un lenguaje de programación orientada a objetos; nuestro propósito es desarrollar en este lenguaje métodos numéricos que permiten las aplicaciones de ingeniería de tal forma que se puedan hacer programas que se bajen por Internet en cualquier parte del mundo.
En esta primera entrega analizaremos la estructura de objetos inicial para poder operar con funciones y polinomios, como primeros métodos veremos como integrar y derivar polinomios y por medio de esto se hallará una de sus raíces. Para las funciones no lineales desarrollaremos el método de la bisección para encontrar una raíz
Clases: Se definio entonces una clase padre de nombre MetodoNumerico, pensemos cual podria ser datos generales para cualquier método numérico, esto es tolerancia y el número máximo de iteraciones, deberia ser estaticas pues no se podria considerar que la toleracia sea un dato para cada instancia de la clase, sino más bien se pertenece a la clase, es por esta razon que se la definio static.

public class MetodoNumerico {
/* número de digitos calculados de la raiz */
public static double tolerancia=5E-7;
/* Máximo número de iteraciones */
public static int maxIteraciones=30;
public MetodoNumerico() {
} public MetodoNumerico(double tol, int maxIter)
{
MetodoNumerico.tolerancia=tol;
MetodoNumerico.maxIteraciones=maxIter;
}
}
Un constructor que me permita modificar los valores de tolerancia y el número máximo de iteraciones, el cual por herencia puede ser usado en las subclases de ella.
-
Polinomios
Un polinomio se halla definido como:

los métodos que se desarrollaron fueron la derivación, la integración y el método de Newton para hallar una raíz.
Estos conceptos dan lugar en terminos de Java a la creación de una subclase de MetodoNumerico de nombre Polinomio, las cuales a su vez se relacionan directamente con métodos de resolución analitica (Derivacion e Integración) y numérica (Método de Newton).
public class Polinomio extends MetodoNumerico {
/*————————————————–
grado y coeficiente son atributos de cada uno de los Polinomios
especificos a crear (Instancias),gradoMax es el maximo valor de grado que puede poseer un Polinomio
————————————————–*/
/* máximo grado del polinomio es MaxGrado -1 */
private static int gradoMax=20;
/* número de digitos calculados de la raiz */
// private final static double tolerancia=5E-7;
/* Máximo número de iteraciones */
// private final static int maxIteraciones=30;
private int grado; public double[] coeficientes=new double[Polinomio.gradoMax];
/* Constructor de Polinomio */
public Polinomio() {
super();
// super.tolerancia=5E-3;
/* Máximo número de iteraciones */
//super.maxIteraciones=30;
}
/*Constructor de Polinomio con dos argumentos
el grado del polinomio y los coeficientes.
*/ public Polinomio(int grado,double[] coeficientes) {
this();
this.grado=grado;
this.coeficientes=coeficientes;
}
/* Constructor de Polinomio con dos argumentos
el grado del polinomio y los coeficientes.
*/
public Polinomio(int grado,double[] coeficientes,double tol, int maxIter) {
// this();
super(tol,maxIter);
this.grado=grado;
this.coeficientes=coeficientes;
}
El código aquí mostrado nos permite realizar los siguientes analisis, creamos una variable static, de nombre gradoMax, que es el máximo grado de los polinomios, existen ademas dos atributos, uno de ellos de nombre grado que será double y que al crear las instancias cada polinomio que se cree tendra su propio grado, por tanto este será un atributo que pertenecera a cada instancia de Polinomio que se cree, bajo el mismo analisis podemos decir que tenemos el vector de tipo double de nombre coeficientes,
public double[] coeficientes=new double[Polinomio.gradoMax];
en este vector se almacenara la solución del problema
Cada polinomio definido sera una instancia de la clase Polinomio, y este tendra su vector de coeficientes en su correspondiente atributo coeficientes.
double a[] = {6 , 11, 6, 1};
Polinomio p1=new Polinomio(3,a);
Para el ejemplo grado 3 y los coeficientes que se encuentran en el vector a.
Hemos entonces creado el polinomio 
-
Derivación e Integración
Vamos a recurrir a la propiedad de los polinomios mediante la cual se puede encontrar su derivada mediante la expresión

Y cuando se integra un polinomio obtendremos el siguiente polinomio:

Donde C es una constante de integración.
/* Este metodo me permite calcular los valores de los coeficientes de la derivada del polinomio
*/
public double[] coeficientesDerivada()
{ double derivadas[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ derivadas[i-1]=(i)*this.coeficientes[i];
}
return derivadas;
}
/* Este método nos permite obtener el polinomio correspondiente al valor de la derivada del polinomio dato
*/
public Polinomio derivada()
{ double derivadas[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ derivadas[i-1]=(i)*this.coeficientes[i];
}
return new Polinomio(this.grado,derivadas);
}
/* Este método nos permite calcular los valores de los coeficientes de la integral del polinomio con costante de integracion igual a 0
*/
public double[] coeficientesIntegral()
{ double integral[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ integral[i+1]=this.coeficientes[i]/(i+1);
}
integral[0]=0;
return integral;
}
/* Este método permite calcular los valores de los coeficientes de la integtral del polinomio con costante de integracion igual dado por la llamada al metodo
*/
public double[] coeficientesIntegral(double psi)
{ double integral[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ integral[i+1]=this.coeficientes[i]/(i+1);
}
integral[0]=psi;
return integral;
}
/* Este metodo permite obtener el polinomio correspondiente al valor de la integral del polinomio dato con costante de integracion igual a 0
*/
public Polinomio integralPolinonio()
{ double integral[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ integral[i+1]=this.coeficientes[i]/(i+1);
}
integral[0]=0;
return new Polinomio(this.grado,integral);
}
/* Este metodo permite obtener el polinomio correspondiente al valor de la integral del polinomio dato con costante de integracion igual dado por la llamada al metodo
*/
public Polinomio integralPolinonio(double psi)
{ double integral[]=new double[Polinomio.gradoMax];
for (int i=1; i<=this.grado; i++)
{ integral[i+1]=this.coeficientes[i]/(i+1);
}
integral[0]=psi;
return new Polinomio(this.grado,integral);
}
}
/* evaluaPolinomio es el metodo que evalua el polinomio para un valor de x dado, notese que se debera aplicar este metodo en la instancia debido a que es un método miembro de la clase Polinomio
*/
public double evaluaPolinomio(double x){
double b;
int n = this.grado;
b = this.coeficientes[this.grado];
for (int i= –n; i>=0; i–)
{
b = b * x + this.coeficientes[i];
}
return b;
}
/* evaluaPolinomioS Este metodo es static por tanto se pertenece a la clase, y la instancia u objeto debe ingresar como argumento del método.
*/
public static double evaluaPolinomioS(Polinomio p1,double x){
double b;
int n = p1.grado;
b = p1.coeficientes[p1.grado];
for (int i= –n; i>=0; i–)
{
b = b * x + p1.coeficientes[i];
}
return b;
}
public double evaluaDerivadaPolinomio (double x)
{
double b;
int n = this.grado;
b = this.grado * this.coeficientes[this.grado];
for (int i= –n; i>=1; i–)
{
b = b * x + i * this.coeficientes[i];
}
return b;
}
Este es un método analitica de solución el cual tiene su ejemplificacion en el método de nombre coeficientesDerivada y coeficientesIntegral, que se puede observar en el diagrama de clases arriba descritos.
-
Método de newton para la obtención de una raíz

Sea un polinomio P(X) y dado un valor X0 en las cercanías de una raíz nosotros podemos usar la recta tangente para poder encontrar un valor más cercano por medio de:

Repetimos el procedimiento hasta que entre dos valores consecutivos se hayan encontrado cierta cantidad K de dígitos iguales usando para ello

entonces la raíz será el valor de Xn
En la clase Polinomio podemos ver ademas el método newtonPolinomio, que emplea el método arriba descrito.
public double newtonPolinomio (double xEntrada)
{ int i;
double x, xAnt,fx, fDx;
i = 0;
x = xEntrada;
fx=this.evaluaPolinomio(x);
while (i
{ i++;
fDx = this.evaluaDerivadaPolinomio(x);
xAnt = x;
x = x - fx / fDx;
fx = this.evaluaPolinomio(x);
if (Math.abs((x - xAnt) / xAnt) < Polinomio.tolerancia)
i = Polinomio.maxIteraciones;
}
return x;
}public String newtonPolinomioString (double xEntrada)
{ int i;
double x, xAnt,fx, fDx;
String xString=”Trabajando”;
i = 0;
x = xEntrada;
fx=this.evaluaPolinomio(x);
while (xString == “Trabajando”)
{
if (Math.abs(x) < Polinomio.casiCero)
xString = “Fallo x = 0″;
else
{ i++;
fDx = this.evaluaDerivadaPolinomio(x);
if(Math.abs(fDx) < Polinomio.casiCero)
xString = “Fallo Derivada = 0″;
else
{
xAnt = x;
x = x - fx / fDx;
fx = this.evaluaPolinomio(x);
if(Math.abs((x - xAnt) / xAnt) < Polinomio.tolerancia)
xString = “”+x;
else
{if(i == Polinomio.maxIteraciones)
xString = “Fallo máximas iteraciones”;
}
}
}
}
return xString;
}
}
Funciones No Lineales
La clase correspondiente nos encontramos desarrollandola aun, pero hemos decidido adelantarles nuestro trabajo inicial.
-
Método de la bisección.
El método de la bisección se halla basado en la propiedad de que el valor de la función cambia de signo en los alrededores de una raíz.

Necesitaremos un intervalo [a,b] donde dicha función cambie de signo ( f(a)*f(b)<0) pues allí casi con seguridades encontrara una raíz. Se encuentra a continuación el centro del intervalo ( X = ( a + b ) / 2 ) y se verifica que f ( a ) * f ( x ) < 0 si esto ocurre se le asigna b = x caso contrario a = x reduciendo el ancho del intervalo a la mitad, este proceso continua reduciéndolo hasta que este sea menor que un cierto valor de tolerancia. Cuando se alcanza dicha condición la raíz se encontrara en el centro del intervalo ( raíz ( a + b ) / 2 )..
class Funcion extends MetodoNumerico {
/*
Constructor que permite llamar al super constructor MetodoNumerico
*/
public Funcion()
{
}
public Funcion(double tol, int maxIter)
{ super(tol,maxIter);
}
/*
el metodo biseccion que encuentra ceros de la funcion a traves del metodo de la biseccion
*/
public double biseccion (double xo, double xf)
{
double x,fx,xant=0;
int i=0;
double fo=f(xo);
do {
x = (xo + xf)/2;
fx = f(x);
i++;
if (fo*fx<=0)
{
xf = x;
}
else {
xo = x;
fo = fx;
}
if (Math.abs((x-xant)/x)
{
i=MetodoNumerico.maxIteraciones;
}
else {
xant = x;
}
}
while (i>=MetodoNumerico.maxIteraciones);
return (xo + xf)/2;
}
}
Pregunta:
Donde se podría definir el método f(), por cierto falta aqui.
