Listo Newton_Raphson, hay que pulir ciertos detalles de presentación, pero funciona, por favor lo prueban, lo optimizan y me comentan sobre su funcionamiento, el código esta echo de tal manera que muestra los pasos de la ejecución para hacerlo mas didáctico, estas sentencias se pueden eliminar.
He visto muchos códigos de Newton_Raphson en la red pero todos cometen un grave error, no chequean si la derivada retorna cero, creando una indeterminación, por ende el programa termina abruptamente, ademas mi codigo si no converge llama nuevamente a la función principal
// versión 1.0.0 ultima edicion 28/Oct/2014
// By ingmarov and JAIMEZA aka (compsystems) www.jaimeza.org
// Para ejecutar este codigo use PSEINT http://pseint.sourceforge.net
// http://es.wikipedia.org/wiki/M%C3%A9todo_de_Newton
// [youtube]opLpVhq4Vjo[/youtube]
// ejempo 1*x^3-6*x^2+11*x-6*x^0 polinomio de grado 3, tiene 4 coeficientes visto en forma vectorial o de arreglo como [ 1, -6, 11, -6 ]
// raices {1,2,3}
// funcion auxiliar
funcion valor_retorno = evalPolinomio( copia_Pol, orden_Pol, val_x ) // Esta función como su nombre lo indica evalúa un polinomio de orden n en el valor x
Definir valor_retorno, acumSum, polEval como real;
Definir k Como Enteros;
acumSum = 0; // valor inicial de la expresion a evaluar
Escribir " ";
Para k = 0 Hasta orden_Pol Con Paso 1 Hacer // segun el ejemplo si 1*x^3+6*x^2+11*x+6*x^0 entonces inicia ciclo entre 0 y 3
polEval = (copia_Pol[k+1]* (val_x)^(orden_Pol-k) );
//Imprimir polEval;
acumSum = acumSum + polEval;
//Imprimir "para k =" k, " Acumulado = ", acumSum;
// Ejemplo
// para k = 0 extrae el coeficente de la posicion 1 y lo multiplica por el valor de x^(3-0) => 1*x^3 y le suma el valor acumulado anterior
// para k = 1 extrae el coeficente de la posicion 2 y lo multiplica por el valor de x^(3-1) => x^2 y le suma el valor acumulado anterior
// para k = 2 extrae el coeficente de la posicion 3 y lo multiplica por el valor de x^(3-2) => x^1 y le suma el valor acumulado anterior
// para k = 3 extrae el coeficente de la posicion 4 y lo multiplica por el valor de x^(3-3) => x^0 y le suma el valor acumulado anterior
FinPara
valor_retorno = acumSum; // valor_retorno es la variable que contiene el valor de retorno cuando se invoca desde otra funcion o proceso
FinFuncion
// funcion auxiliar
funcion Newton_Raphson()
Dimension Pol[10]; // Se crean un arreglo para almacenar los coeficientes del polinomio (maximo 10 coeficientes)
Dimension derPol[9]; // Se crean un arreglo uno para almacenar los coeficientes de la derivada. (maximo 9 coeficientes)
Definir Pol, derPol Como Entero; // tipo de coeficientes enteros para el polinomio y derivada
Definir n Como Entero; // variable para el grado del poninomio
Definir i, ci Como Entero; // variables contadores
Escribir "Bienvenido!, esta aplicación le ayudará a localizar la raices de un polinomio p(x) usando el algoritmo de Newton-Raphson";
Escribir Sin Saltar "Escriba el grado del polinomio n= ";
Leer n;
Escribir "Escriba los coeficientes del polinomio ordenado de forma canónica descendente";
// Ciclo Para: sirve para leer los coeficientes del polinoio y hallar su derivada.
Para ci = 1 Hasta n+1 Hacer // un polinomio de grado n, tiene n+1 coeficientes
Escribir Sin Saltar "ingrese coeficiente ", ci, " = ";
Leer Pol[ci]; // asignar por lectura de teclado cada coeficiente del polinomio
Si ci < n+1 Entonces // la derivada del x^0 es cero por eso no se incluye
derPol[ci] = Pol[ci]*( (n-ci)+1); // asigna el valor de la derivada en la formacion o arreglo delPol
FinSi
FinPara
Para ci = 1 Hasta n+1 Hacer // Esto no es necesario pero lo que hace es escibir el polinomio.
Si ci < n Entonces
Escribir Sinsaltar Pol[ci],"*x^", n-(ci-1), "+";
Sino
Si ci=n Entonces // para x^1
Escribir Sinsaltar Pol[ci],"*x+"; // extrae el valor del coeficiente de x^1
Sino
Escribir Pol[ci]; // para x^0
FinSi
FinSi
FinPara
Escribir "Derivada"; // Este escribe el polinomio correspondiente a la derivada.
Para ci = 1 Hasta n Hacer
Si ci < n-1 Entonces
Escribir Sinsaltar derPol[ci],"*x^", n-ci, "+";
Sino
Si ci=n-1 Entonces
Escribir Sinsaltar derPol[ci],"*x+";
Sino
Escribir derPol[ci];
FinSi
FinSi
FinPara
// Esta es la iteración propia del algoritmo de Newton_Raphson
Definir x0, x1, iter, flag_salida, p_x0, dp_x0 como real;
Definir test1, test2 como logico;
Definir EPS Como Real; // criterio de exactitud
//Escribir "criterio de convergencia EPS= " sin saltar;
//leer EPS; // margen de error;
Definir EPS1 Como Real; // criterio de exactitud
Escribir "criterio de exactitud, tolerancia EPS1= " sin saltar;
leer EPS1; // margen de error;
Definir max_iter Como Entero;
Escribir Sin Saltar "Ingrese el numero de iteraciones maximo permitido";
Leer max_iter;
Escribir "El polinomio tiene ", n , " raices";
Escribir "Ingrese el valor inicial, absisa cercana a la raíz x0 = " sin saltar;
Leer x0; // Este es el primer valor almacenado para comenzar la iteración
flag_salida = 0;
iter = 1; // iteracion inicial
p_x0 = evalPolinomio( Pol, n, x0 ); // Se evalúa al polinomio en el valor x0
Escribir "Pol(", x0, ")= ", p_x0; // imprime el valor resultante
test1 = abs(p_x0)>EPS1; // el valor de x0 no cumple el criterio de exactitud
escribir "abs(p_x0)>=EPS1: ", abs(p_x0), ">", EPS1, ": ", test1;
test2 = iter <= max_iter;
escribir "iter <= max_iter: ", iter "<=" max_iter, ": ", test2;
Mientras test2 y test1 Hacer
escribir " "
escribir "ITER #", iter;
escribir "x0=", x0;
test2 = iter <= max_iter;
escribir "iter <= max_iter: ", iter "<=" max_iter, ": ", test2;
p_x0 = evalPolinomio( Pol, n, x0 ); // Se evalúa al polinomio en el valor x0
Escribir "Pol(", x0, ")= ", p_x0; // imprime el valor resultante
test1 = abs(p_x0)>EPS1; // el valor de x0 no cumple el criterio de exactitud
escribir "abs(p_x0)=",abs(p_x0);
escribir "abs(p_x0)>=EPS1: ", abs(p_x0), ">", EPS1, ": ", test1;
dp_x0 = evalPolinomio( derPol, n-1, x0 ); // Se evalúa la derivada en el valor x0
Si dp_x0 == 0 Entonces
Escribir "la derivada evaluada en xo es cero, por lo tanto x1 se vuelve indefinido";
Escribir "Escoja otro valor inicial de xo";
iter = max_iter+1; // salida forzosa del loop
flag_salida = 1;
Sino
Escribir "DerPol(", x0, ")= ", dp_x0;
x1 = x0 - (p_x0/dp_x0); // Esta es la definición del algoritmo de Newton-Raphson
//EPS = abs((x1-x0)/x1);
iter = iter+1; // Esto incrementa el número de iteraciones hechas
escribir "x1=", x1;
x0 = x1; // actualiza valor inicial
FinSi
FinMientras
si flag_salida == 0 Entonces
Si iter >= max_iter Entonces
Escribir "El algoritmo no converge";
Escribir "Escoja otro valor inicial de xo, o aumente el numero de iteraciones";
Esperar Tecla;
Newton_Raphson();
Sino
Escribir "";
Escribir "Nos alegramos por que encontramos la raíz";
Escribir "La raíz aproximada es: ", x0;
Escribir "Con una toleracia de ", EPS1;
Escribir "Número de iteraciones = ", iter;
FinSi
finsi
FinFuncion
// funcion principal
Proceso Principal//()
Newton_Raphson();
FinProceso
También pienso agregarle al código anterior, que se repita n veces según el numero de raíces y multiplicidades y soporte de raíces complejas (QUIEN ME AYUDA)
gracias
Jaime