Justificación y propósito
La interpolación es utilizada para hacer predicciones de un valor que se encuentra entre una serie de puntos obtenidos de observaciones experimentales o empíricas. En otras palabras, valores que no pudieron ser medidos u observados en alguna clase de experimento.
El algoritmo de interpolación encuentra una función que cruza todos los puntos dados, y de esta manera, es posible evaluar cualquier valor dentro del valor mínimo y el máximo de dichos puntos para estimar cualquier otro valor. Sin embargo, no significa que no tenga error, de hecho, la función creada no describe el comportamiento real de la información utilizada para la interpolación. Por ejemplo, si se mide la temperatura de cierta región en un lapso de tiempo y se crea una función que, para estos datos, dicha función podrá describir de manera aproximada los datos intermedios, pero los datos fuera del rango pueden no tener sentido o tener un incremento o decremento descontrolado.
Volviendo a algo más específico, la razón por la que se utiliza la interpolación por Newton o Lagrange, es porque estos pueden crear una función con n puntos y, a diferencia de una línea recta (interpolación linear) o una simple parábola (interpolación cuadrática), tiende a generar una mejor precisión en las predicciones de valores intermedios.
Antecedentes
Imaginemos que tenemos 2 puntos:
Podemos dibujar una línea recta entre ellos:
Y elegir un punto arbitrario entre estos puntos:
Así, podemos calcular varias distancias:
Entonces (tomando en cuenta los 2 triángulos que se forman), podemos hacer la siguiente igualdad:
Y resolviendo para f(x):
Explicación gráfica de la interpolación
La interpolación consiste en encontrar una función que cruce por una cierta cantidad de puntos.
En el caso de la interpolación por polinomios de Newton y Lagrange, se puede utilizar cualquier cantidad de puntos. Esto, debido a que estos métodos buscan un polinomio cuyo grado depende de la cantidad de valores conocidos, en otras palabras, utiliza una fórmula generalizada que se puede aplicar sin importar la cantidad de puntos y genera un polinomio que se ajusta a dichos puntos.
El funcionamiento gráfico es exactamente el mismo, una vez que se obtiene el polinomio, este ya se puede utilizar para evaluar el valor intermedio deseado.
Como se muestra en la siguiente imagen, con tres puntos se creó un polinomio de tercer grado que se ajusta a los puntos. Posteriormente, se evalúa en un punto intermedio y se da un valor cercano al real.
Codigo en C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #include <iostream> #include <cmath> #include <vector> using namespace std; double EPSILON = 0.00001; //Error void interpolacionLineal( double y1, double y2, double x1, double x2, double x ) { double y = 0.0; y = y1 + ( y2 - y1 ) * ( x - x1 ) / ( x2 - x1 ); cout << "Valor interpolado es (y): " << y << endl; } void interpolacionCuadrtica ( double y0, double y1, double y2, double x0, double x1, double x2 ) { double b0 = y0; // Diferencia dividida discreta double b1 = ( y1 - y0 ) / ( x1 - x0 ); double b2 = ( ( ( y2 - y1 ) / ( x2 - x1 ) ) - b1 ) / ( x2 - x0); double a = b2; double b = ( b1 - b2 * x1 - b2 * x0 ); double c = ( b0 - b1 * x0 + b2 * x0 * x1 ); cout << "\n++++++++++++++++++++++++++++++" << endl; cout << "b0: " << b0 << "\tb1: " << b1 << "\tb2: " << b2 << endl; cout << "Funcion cuadratica: " << a << "x^2 + " << b << "x + " << c << endl << endl; } /** Metodo utilizado en la interpolacion Polinomial de Newton */ double divisionDiscreta( double *y, double *x, int n, int i, int j, vector<double> *B ) { if ( n == 1 ) { if ( i == 0 ) { B->push_back( y[i] ); cout << "f(x0): " << y[i] << endl; } return y[i]; } else { //cout << "xi: " << i << endl; //cout << "xj: " << j << endl; double val = ( divisionDiscreta( y, x, n - 1, i, j + 1, B ) - divisionDiscreta( y, x, n - 1, i - 1, j, B ) ) / ( x[i] - x[j] ); if ( j == 0 ) { B->push_back( val ); } cout << "f[ x" << i << ", x" << j << " ]: " << val << endl; return val; } } void interpolacionPolinomialNewton() { /* Nota: La suma de los binomios son conmutativas */ double y[] = //{2.31, 3.36, 4.59, 6}; //{0, 1.386294, 1.791759, 1.609438}; {0.1353, 7.3890, 20.0855}; double x[] = //{0.1, 0.4, 0.7, 1}; //{1, 4, 6, 5}; {-2, 2, 3}; double x_inc = -1; vector<double> B; int n = sizeof( y ) / sizeof( y[0] ); divisionDiscreta( y, x, n, n - 1, 0, &B ); // int j = B.size(); double v = 0; cout << "Polinomio: "; //Print Function while ( j --> 0 ) { cout << B[j]; //Print Function double temp = B[j]; int k = j; while ( k --> 0 ) { cout << "(x - " << x[k] << ")"; //Print Function temp *= ( x_inc - x[k] ); } if ( j != 0) //Print Function cout << " + "; //Print Function v += temp; } cout << "\nf(x) = " << v << endl; // El polinomio es: b0 + b1(x - x0) + b2(x - x0)(x - x1) + b3 (x - x0)(x - x1)(x - x2) } /** Formula utilizda en la iterpolacion de Lagrange */ double L( int i, double x_incognita, double *x, int n ) { int j = 0; double val = 1; while ( j < n ) { if ( i != j ) { val *= ( x_incognita - x[j] ) / ( x[i] - x[j] ); } j++; } return val; } double f( double *y, double *x, double x_incognita, int n ) { int i = 0; double val = 0; while ( i < n ) { val += L( i, x_incognita, x, n ) * y[i]; i++; } return val; } void InterpolacionLagrange() { double y[] = //{2.31, 3.36, 4.59, 6}; {0, 1.386294, 1.791759, 1.609438}; double x[] = //{0.1, 0.4, 0.7, 1}; {1, 4, 6, 5}; int n = sizeof( y ) / sizeof( y[0] ); double x_incognita = 10; cout << "y calculada: " << f( y, x, x_incognita, n ) << endl;; } int main() { double y0, y1, y2, x0, x1, x2; // y1 = 86.4; // y2 = 92.5; // x1 = 1.0; // x2 = 1.5; // x = 1.25; // interpolacionLineal ( y1, y2, x1, x2, x ); y0 = 0; y1 = 1.386294; y2 = 1.791759; x0 = 1; x1 = 4; x2 = 6; //interpolacionCuadrtica( y0, y1, y2, x0, x1, x2 ); interpolacionPolinomialNewton(); //InterpolacionLagrange(); return 0; } |
Ejemplos
Input
|
Valor x deseado y f(x) verdadero
|
Output
| ||||||||||
f(x) = ln(x)
|
X = 2
f(2) = 0.69315
X = 3
f(3) = 1.09861
|
Newton:
X = 2
f(x) = 0.628767
X = 3
f(x) = 1.07513
Lagrange:
X = 2
f(x) = 0.628767
X = 3
f(x) = 1.07513
| ||||||||||
f(x) = log x
|
X = 10
f(x) = 1
|
Newton:
X = 10
f(x) = 1.00034
Lagrange:
X = 10
f(x) = 1.00034
| ||||||||||
f(x) = e^x
|
X = -1
f(x) = 0.3678
X = 0
f(x) = 1
X = 1
f(x) = 2.7182
|
Newton:
X = -1
f(x) = -4.58112
X = 0
f(x) = -4.94431
X = 1
f(x) = -0.95427
Lagrange:
X = -1
f(x) = -4.58112
X = 0
f(x) = -4.94431
X = 1
f(x) = -0.95427
|