Polinomio de interpolación de Lagrange: C++ Linux

Si tenemos n pares ordenados correspondientes a Y como una función de X, siempre es posible unirlos mediante una función polinómica a la cual denominaremos polinomio de interpolación. El procedimiento numérico de Lagrange, que da lugar a un polinomio de grado n-1, es el que nos ocupa para el siguiente código:

#include <iostream>
#include <fstream>

using namespace std;

#include <iomanip>

void monomio2(int n, double *x, double *D);

int main () {
	
	cout << "Polinomio de interpolacion de Lagrange\n\n";

	ifstream label1 ("datos//datos.in");
	
	int n, i, j, k;

	label1 >> n;

	double *x, *xp, *f, *L, *D, producto, sum, *P;

	x = new double [n], xp = new double [n], f = new double [n];
	L = new double [n], D = new double [n+1], P = new double [n];

	cout << "Numero de pares ordenados = " << n << "\n\n";

	cout << "Valores de x y f(x)\nx   f(x)\n";

	for (i= 0; i < n; i++){

		label1 >> x[i] >> f[i];
		cout << x[i] << setw(5) << setiosflags(ios::right) << f[i] << "\n";

	}

	cout << endl;

	for (k = 0; k < n; k++){

	producto = 1;

		for (i = 0; i < n; i++){

			if (i != k) producto = producto * (x[k] - x[i]);

		}
	
	L[k] = f[k]/producto;

	}

	cout << "Coeficientes de interpolacion de Lagrange\n\n";

	cout.setf(ios::fixed);

	cout.precision(1);


	for (i= 0; i < n; i++){

		cout << "L(" << n-i-1 << ") = " << setw(4) << setiosflags(ios::right) << L[i] << endl;

	}

	cout << endl;

	for (k = 0; k < n; k++){
	
		j = 0;	
		
		for (i = 0; i < n; i++){

			if (i != k) {xp[j] = x[i]; j += 1;}

		}
	
		monomio2 (n-1, xp, D);

		for (i= 0; i < n; i++){

			P[i] = P[i] + L[k]*D[i];

		}
	 
	}

	cout << "Polinomio de interpolacion de Lagrange (grado " << n-1 << ")\n\n";

	for (i= 0; i < n; i++){

		cout << "P(" << n-i-1 << ") = " << setw(4) << setiosflags(ios::right) << P[i] << endl;
			
	}

	return 0;

}

void monomio2(int n, double *x, double *D){

	double *E;

	E = new double [n];

	D[0] = 1;

	D[1] = -x[0];

	for (int i = 1; i < n; i++) {

		for (int k =1; k < i+1; k++) {

			E[k] = D[k] + D[k-1]*(-x[i]);

		}

		D[i+1] = D[i]*(-x[i]);

		for (int j = 1; j < i+1; j++) {

			D[j] = E[j];

		}

	}

	delete E;

}

Lo emplearemos para encontrar el polinomio de interpolación de Lagrange (de grado 2) a partir de tres pares ordenados (x, f(x)) que generé usando la ecuación de la parábola:

f(x) = x² + 2x -5

Los valores utilizados fueron los siguientes:

x  y
0 -5
1 -2
2  3  

Estos valores, conjuntamente con el número de pares ordenados (colocado al inicio), se incluyeron en el archivo datos/datos.in y se introducen desde el programa principal. El algoritmo usa la función monomio2, que incluye unas ligeras modificaciones en la ya conocida monomio, para permitir en este caso determinar los desarrollos de (x-x1).( x-x2) … (x-xn), en lugar de (x+x1).( x+x2) … (x+xn), para cada i diferente de k. Después de copiar el código y grabarlo como lagrange.c++, abrimos una cónsola y nos vamos hacia la carpeta LAGRANGE y lo compilamos con:

g++ lagrange.c++ -o lagrange

La ejecución del mismo (./lagrange [Enter]) produce esta salida:

Polinomio de interpolacion de Lagrange

Numero de pares ordenados = 3

Valores de x y f(x)
x f(x)
0 -5
1 -2
2 3

Coeficientes de interpolacion de Lagrange

L(2) = -2.5
L(1) = 2.0
L(0) = 1.5

Polinomio de interpolacion de Lagrange (grado 2)

P(2) = 1.0
P(1) = 2.0
P(0) = -5.0

donde se verifica que los coeficientes del polinomio cuadrático obtenido ajustan perfectamente a la ecuación f(x) = x² + 2x -5 ya referida. Sin embargo, no nos emocionemos tanto por este éxito. Si incluimos, por ejemplo, 10 pares ordenados para los valores experimentales de una variable como función de otra, el polinomio que obtendríamos sería de grado 9 y, aunque pasará por todos los puntos considerados, la gráfica que obtendremos posiblemente se comportará de una manera no deseada fuera de ellos. Existen técnicas de interpolación más poderosas como la de los splines pero, este caso, es válido e interesante como ejercicio de programación.

This entry was posted in Código C++. Bookmark the permalink.

21 Responses to Polinomio de interpolación de Lagrange: C++ Linux

  1. Debido a que hice un copy/paste de posts que estaban anteriormente en blogger, he podido encontrar algunos errores. Sin embargo, como detecté visita en este, me dispuse a “bajarlo” y ejecutarlo y no tiene problemas en su operación. También aproveché para corregir el código resaltado.

  2. James says:

    Excelente el algoritmo!
    muchas gracias!

  3. Uso gmail (aunque tu también) y no creo que me lo puedas enviar y yo recibir si es un *.exe. Lo más conveniente es que lo “cuelgues” en algún sitio y me indiques el link de descarga. Si es el código fuente lo puedes colgar en un comentario y si es tu deseo no tenerlo allí yo lo “elimino”.

    Saludos

  4. James says:

    Vale, dejame mañana los subo a megaupload,
    la idea es darte los fuentes y ningun exe, también tengo el que me genera los polinomios divididos de newton!

  5. James says:

    Estimado Jose

    Te comparto el archivo con:

    -Neville (No recursivo)
    -Lagrange (Version tuya traducida a excel)
    -Diferencias Divididas de newton

    http://www.megaupload.com/?d=WQSLQ75S

    Espero que sea de tu agrado.

    Gracias.

  6. javo says:

    Oye brother a mi no me corre tu programa, compila, pero me aparece una repetición de “00”, porqué??

  7. ALEXEY says:

    hola he visto tu programa tengo dudas de como generas el archivo datos.in que formato tiene, mmm x cierto si estoy trabajando en windows puedo tener algun problema??…saludos

    • Tienes razón, puede causar confusión. El datos.in, para este ejemplo, es este:

      3
      0 -5
      1 -2
      2  3  
      

      y tiene que ir dentro de una carpeta llamada datos.

      Con relación a la compilación no creo que de problemas. Si compila y no ves nada lo que hay que agregar es un system(“pause”); que no es necesario en Linux,

  8. hola , yo lo compilo con dev c++ y bueno el datos.in supuce que es un archivo de dev igual, asi que lo hice y lo guarde en el escritorio dentro de una carpeta que se llama datos pero, no lo llama me ayudas porfa

    • Hay una omisión en el programa, que ya fue corregida, que no produce malos resultados en Linux pero si en Windows y en Python (violación de segmento). Compila nuevamente el código de arriba. Colócalo en una carpeta llamada monomio. Dentro de ella crea otra que se llama datos y dentro de ésta colocas el datos.in con estos valores:

      3
      0 -5
      1 -2
      2  3  
      

      El problema más común al crear el datos.in es que, por defecto, Windows no te deja modificar las extensiones y, por tanto, la mayoría crea un datos.in.txt y no lo sabe. Esto se corrige con lo siguiente:

      En Mi PC, menú Herramientas, se accede a las Opciones de carpeta. En esta nueva ventana seleccionamos la pestaña Ver y en la lista de Configuración Avanzada se desmarca la opción Ocultar las extensiones de archivo para los tipos de archivo conocidos. A continuación Aceptar y ya tendremos visibles las extensiones de los archivos.

      La imagen siguiente es ilustrativa de como debe quedar todo:

      lagrange

      Al hacer click en el ejecutable debería aparecer algo similar a esto (ya lo comprobé):

      Polinomio de interpolacion de Lagrange
      
      Numero de pares ordenados = 3
      
      Valores de x y f(x)
      x   f(x)
      0   -5
      1   -2
      2    3
      
      Coeficientes de interpolacion de Lagrange
      
      L(2) = -2.5
      L(1) =  2.0
      L(0) =  1.5
      
      Polinomio de interpolacion de Lagrange (grado 2)
      
      P(2) =  1.0
      P(1) =  2.0
      P(0) = -5.0
      
  9. Marce says:

    ¡Hola!
    Estoy intentando ejecutarlo sobre windows, con Visual Studio. En la carpeta donde está el *.exe creo otra para guardar el archivo de datos.in, pero a la hora de ejecutar me aparecen puros pares ordenados de ceros y no sólo son 3 sino miles ¿Qué crees que esté haciendo mal?

    • Que tu datos.in es en realidad un datos.in.txt porque, por defecto, Windows te lo crea de esa manera. La solución es esta:

      En Mi PC, menú Herramientas, se accede a las Opciones de carpeta. En esta nueva ventana seleccionamos la pestaña Ver y en la lista de Configuración Avanzada se desmarca la opción Ocultar las extensiones de archivo para los tipos de archivo conocidos. A continuación Aceptar y ya tendremos visibles las extensiones de los archivos.

      Así podrás modificar tu datos.in.txt a datos.in.

      • Marce says:

        No es eso. Ya había leído previamente la sugerencia al respecto y me cercioré de que la extensión fuera sólo *.in y no *.in.txt.
        He visto que también sugieres que se incluya un system(“pause”);
        ¿Dónde se coloca esta línea? … Quizás ése sea el problema… no lo sé

  10. Puede ser. Cuando esté en Windows lo compilo allí y te digo.

    Nota: Ya lo compilé en Windows y no produce los valores esperados. No tengo tiempo de averiguar el por qué. Sin embargo, en Linux trabaja bien y la versión Python de monomio también. Es extraño que no sea portable.

  11. juan says:

    amigo quiero en ves de hacer 3 interaciones 5

    • Modifica el datos.in de tal manera de tener 5 pares ordenados. Sin embargo, ahora vas a obtener un polinomio de grado 4.

      Si requieres la expresión funcional para alguna acción específica (por ejemplo, calcular el área bajo la curva) entonces lo que hay que hacer es agrupar por lotes de a tres tomando en cuenta si el número de puntos es par o impar.

  12. Efra Pal says:

    Amigo tendrás el código del polinomio de lagrange en visual basic? por favor

Leave a reply to javo Cancel reply