Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Facultad de ciencias
Escuela de Física
Proyecto Nº1
Presentado a:
Prof. ILIA DAVIDOVICH MIKHAILOV
Bucaramanga
2014
1. Problemas para Tarea N 1 (raíces de una ecuación algebraica)
( ) ( ), Con
Para este caso se tomó , donde se aprecia que sin importar el valor que se le dé a p,
h (paso) siempre es un intervalo que contiene una única raíz (figura 1)
Figura 2. Grafica para p= 0.5 con zoom. La línea punteada representa la última raíz, y el paso es
un múltiplo de corte con el eje x.
Figura 3. Grafica para p= 5.0. La línea punteada representa la primera raíz.
p=0.5 12 6.911504
13 7.539822
n raíz 14 8.168141
1 1.177065 15 8.796459
2 6.192728 16 9.424778
3 12.570099 17 10.053096
4 18.849395 18 10.681415
19 11.309734
p=5.0 20 11.938052
21 12.566371
n raíz 22 13.194689
1 0.117707 23 13.823008
2 0.619273 24 14.451326
3 1.257010 25 15.079645
4 1.884939 26 15.707963
5 2.513275 27 16.336282
6 3.141593 28 16.964600
7 3.769911 29 17.592919
8 4.398230 30 18.221237
9 5.026548 31 18.849556
10 5.654867 32 19.477874
11 6.283185
El código del programa se realizó en lenguaje C, usando el compilador Code::Blocks 13.12.
#include<stdio.h>
#include<math.h>
FILE *fdat1;
fdat1=fopen("Punto1b_5.0.dat","w");
xl=a;
xr=a+h;
fprintf(fdat1,"%2s %6s \n","n","raíz");
while(xr<b){
yl=fun(xl);
yr=fun(xr);
if(yl*yr<0.0){
cont++;
xraiz=Raiz(xl,xr,tol);
fprintf(fdat1,"%2d %6lf\n",cont,xraiz);
}
xl=xr;
yl=yr;
xr=xl+h;
yr=fun(xr);
}
fclose(fdat1);
return 0;
}
xl=a;
fl=fun(xl);
xr=b;
fr=fun(xr);
x=(xl+xr)/2.0;
f=fun(x);
while(f != 0 && (xr-xl)>tol){
if(f*fl<0){
xr=x;
fr=f;
}
else{
xl=x;
fl=f;
}
x=(xl+xr)/2.0;
f=fun(x);
}
return x;
}
El código de este programa es el mismo para cada uno de los dos valores de p
respectivamente.
c) Presente el gráfico del número de las raíces n en función del parámetro p para dentro
del intervalo
Se aprecia que el comportamiento del grafico (figura 4) es lineal (R=0.9989), esto se debe a
que a medida que el valor de p aumenta, los cruces o interceptos entre las funciones
también lo hacen, ya que la función ( ) aumenta su frecuencia debido a que p se
encuentra como su argumento, esto se corrobora en la figura 3.
Figura 4. Gráfica del número de raíces n en función del parámetro p, aumentando en intervalos
de 0.225.
#include<stdio.h>
#include<math.h>
double fun(double x,double p);
double Raiz(double a,double b,double p,double tol);
void allraiz(double a,double b,double p,double tol,double hraiz,int *nraiz,double
xraiz[1000]);
int main(){
double a=0.0,b=20.0,p0=0.5,pf=5.0,p,tol=pow(10,-8),hraiz=0.001,xraiz[1000],hp;
int nraiz,i,np=21,j;
FILE *fdat1;
fdat1=fopen("cantidad de raices.dat","w");
hp=(pf-p0)/(np-1);
for(j=1;j<=np;j++){
p=p0+(j-1)*hp;
fclose(fdat1);
return 0;
}
//Función externa
double fun(double x, double p){
double y;
y=exp(-p*x)-sin(p*x);
return y;
}
Se puede determinar que con la precisión que opto, los dos métodos arrojan resultados
similares, pero a la hora de mirar la cantidad de iteraciones, el método de bisección realizo
17, lo cual es mucho más que 2, las realizadas por el método de newton ; por lo que hace
que el método de newton sea más óptimo refiriéndonos al ámbito de la programación.
int main(){
double a=0.0,b=20.0,p0=0.5,pf=5.0,p,eps=pow(10,-
8),hraiz=0.001,xraiz1,xraiz2,hp,xl,xr,fl,fr,xlu,xru;
int nraiz=0,i,nit1,nit2;
hp=(pf-p0)/9;
//hp=1.0;
FILE *fdat1;
fdat1=fopen("raices dif_metodos.txt","w");
fprintf(fdat1,"%6s %6s %12s %4s %12s %4s\n","p","#raiz","raiz bisecc","#it","raiz
newton","#it");
for(i=1;i<=10;i++){
p=p0+(i-1)*hp;
nraiz=0;
xl=a;
xr=a+hraiz;
fl=fun(xl,p);
fr=fun(xr,p);
xlu=xl;
xru=xl;
while(xr<b){
if(fl*fr<0){
nraiz++;
xlu=xl;
xru=xr;
}
xl=xr;
fl=fr;
xr=xl+hraiz;
fr=fun(xr,p);
}
xraiz1=bisec(xlu,xru,p,eps,&nit1);
xraiz2=newt(xlu,xru,p,eps,&nit2);
fprintf(fdat1,"%6.2lf %6d %12.7lf %4d %12.7lf %4d\n",p,nraiz,xraiz1,nit1,xraiz2,nit2);
}
fclose(fdat1);
return 0;
}
//Funcion original
double fun(double x, double p){
double y;
y=exp(-p*x)-sin(p*x);
return y;
}
//Primera derivada de la funcion original
double dfun(double x,double p){
double y;
y=-p*exp(-p*x)-p*cos(p*x);
return y;
}
//segunda derivada de la funcion original
double ddfun(double x,double p){
double y;
y=(p*p)*exp(-p*x)+(p*p)*sin(p*x);
return y;
}
( ) ( ), Con
Tabla2. Valores de la función con precisión =0.1
i xi yi
1 0 0
2 0.314159 0.071138
3 0.628319 0.184565
4 0.942478 0.260384
5 1.256637 0.274482
6 1.570796 0.224760
7 1.884956 0.143500
8 2.199115 0.079511
9 2.513274 0.029865
10 2.827433 0.006146
11 3.141593 0.000000
b) usando estas dos tablas como valores de una función desconocida calcúlese valores de la
función sobre la malla equidistante * + usando la
fórmula de interpolación de LaGrange global y compare los resultados con los valores
exactos de la función ( ).
El código funciona para los valores de precisión =0.1 y =10-6, dichos valores se
encuentras en los archivos de texto tabla_1 y tabla_2 y genera un archivo de salida en el
cual se imprimen los valores de X, el valor exacto de la función Yexac y los valores al
hacer la interpolación de LaGrange Ylag para cada uno de los valores de . Se procede a
graficar el resultado de dichos archivos, con ayuda del programa Graph. En la figura44444
se observa la relación entre el valor exacto de la función y la interpolación de LaGrange
( =0.1), donde se puede apreciar que el comportamiento entre dichas graficas es semejante
en una buena cantidad de puntos. En fa figura 44445 representa la misma relación anterior
excepto que el valor de la precisión es =10-6 lo que hace que su comportamiento sea
aproximadamente el mismo. Se puede deducir de estas dos graficas que en general el
método de interpolación de LaGrange es bueno, pero es necesario tener en cuenta el error y
la precisión con la que se esté trabajando.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define PI 3.14159265
double function(double xn);
double lagrange(double x[],double y[],int N,double xn);
int main(){
double e,a,b,I;
char t;
int s=201,i=0,N;
FILE *variable1;
variable1=fopen("tabla_1.txt","r");
fscanf(variable1,"%d %lf %lf %lf", &N,&e,&a,&b);
double x[N],y[N];
for(i=0;i<N;i++)fscanf(variable1,"%lf %lf\n", &x[i], &y[i]);
fclose(variable1);
double yn[s],yp[s],xn[s];
I=(b-a)/(s-1);
xn[0]=a;
for(i=0;i<s;i++){
yn[i]=lagrange(x,y,N,xn[i]);
yp[i]=function(xn[i]);
xn[i+1]=xn[i]+I;
}
variable1=fopen("interpolado_1.txt","w");
fprintf(variable1,"X Ylag X Yexac\n");
for(i=0;i<s;i++)fprintf(variable1,"%lf %lf %lf %lf\n",xn[i],yn[i],xn[i],yp[i]);
fclose(variable1);
return 0;
}
double lagrange(double x[],double y[],int N,double xn){
double yn=0.0,L=1.0;
int i=0,j=0;
for(i=1;i<=N;i++){
L=1.0;
for(j=1;j<=N;j++){
if(i!=j)L=L*(xn-x[j])/(x[i]-x[j]);
}
yn=yn+L*y[i];
}
return yn;
}
double function(double xn){
double yp;
yp=exp(-xn)*(sin(xn)*sin(xn));
return yp;
}
c) Repitiese el cálculo del punto anterior usando las interpolaciones segmentarias lineal y
parabólica y explíquese las diferencias que aparecen en estos cálculos.
Figura 7. Gráfica de los valores exactos e interpolación segmentaria lineal para =0.1
Figura 8. Gráfica de los valores exactos e interpolación segmentaria lineal para =10^-6
#include<stdio.h>
#include<math.h>
double lineal(double a,double h,double xe[],int ne,double p);
int main (){
int ne=11,i,j,np=201;
double pe1[ne],xe1[ne],pe2[ne],xe2[ne],x1,x2,p0=0,pf=3.141592,p,hp,d;
FILE *fdat1;
fdat1=fopen("tabla_presicion_0.1.txt","r");
for(i=0;i<11;i++){
fscanf(fdat1,"%lf %lf",&pe1[i],&xe1[i]);
}
FILE *fdat2;
fdat2=fopen("tabla_presicion_0.000001.txt","r");
for(i=0;i<11;i++){
fscanf(fdat2,"%lf %lf",&pe2[i],&xe2[i]);
}
fclose(fdat1);
fclose(fdat2);
d=(pf-p0)/(ne-1);
FILE *fdat3;
fdat3=fopen("seg_lineal_0.1 1.txt","w");
FILE *fdat4;
fdat4=fopen("seg_lineal_0.000001.txt","w");
hp=(pf-p0)/(np-1);
for(j=0;j<=1;j++){
for(i=1;i<=np;i++){
p=p0+hp*(i-1);
if(j==0){
x1=lineal(p0,d,xe1,ne,p);
fprintf(fdat3,"%9lf %9lf\n",p,x1);
}
if(j==1){
x2=lineal(p0,d,xe2,ne,p);
fprintf(fdat4,"%9lf %15lf\n",p,x2);
}
}
}
fclose(fdat3);
fclose(fdat4);
return 0;
}
Figura 10. Gráfica de los valores exactos e interpolación segmentaria parabólica para =10^-6
El código del programa se realizó en lenguaje C, usando el compilador Code::Blocks 13.12.
#include<stdio.h>
#include<math.h>
double cuadratica(double a,double h,double xe[],int ne,double p);
int main (){
int ne=11,i,j,np=201;
double pe1[ne],xe1[ne],pe2[ne],xe2[ne],x1,x2,p0=0,pf=3.141592,p,hp,d;
FILE *fdat1;
fdat1=fopen("tabla_presicion_0.1.txt","r");
for(i=0;i<11;i++){
fscanf(fdat1,"%lf %lf",&pe1[i],&xe1[i]);
}
FILE *fdat2;
fdat2=fopen("tabla_presicion_0.000001.txt","r");
for(i=0;i<11;i++){
fscanf(fdat2,"%lf %lf",&pe2[i],&xe2[i]);
}
fclose(fdat1);
fclose(fdat2);
d=(pf-p0)/(ne-1);
FILE *fdat3;
fdat3=fopen("seg_parabol_0.1 1.txt","w");
FILE *fdat4;
fdat4=fopen("seg_parabol_0.000001.txt","w");
hp=(pf-p0)/(np-1);
for(j=0;j<=1;j++){
for(i=1;i<=np;i++){
p=p0+hp*(i-1);
if(j==0){
x1=cuadratica(p0,d,xe1,ne,p);
fprintf(fdat3,"%9lf %15lf\n",p,x1);
}
if(j==1){
x2=cuadratica(p0,d,xe2,ne,p);
fprintf(fdat4,"%9lf %15lf\n",p,x2);
}
}
}
fclose(fdat3);
fclose(fdat4);
return 0;
}
double cuadratica(double a,double h,double xe[],int ne,double p){
double x,pk,pk1;
int k;
k=(p-a)/h;
if(k==(ne-1))k=k-1;
xe[5]=xe[4];
pk=a+(k)*h;
pk1=pk+h;
x=xe[k]+((xe[k+1]-xe[k])*(p-pk)/h)+((xe[k+2]-2*xe[k+1]+xe[k])*(p-pk)*(p-
pk1)/(2*pow(h,2)));
return x;
}