6.6 Passagem de ponteiro para função
É possível enviar para uma funçao o endereço de outra função. O
próprio nome da função é o endereço da função.
Exemplo 6.6.1. Implemente uma função que eleva outra função ao
quadrado.
#include <stdio.h>
#include <math.h>
double f(double x)
{
return exp(-x);
}
double g(double x)
{
return sin(x);
}
double Quad(double (*fun)(double),double x)
{
return ((*fun)(x))*((*fun)(x));
}
void main (void)
{
double x=2;
printf("f(%f)=%f\n",x,f(x));
printf("g(%f)=%f\n",x,g(x));
printf("(f(%f))^2=%f\n",x,Quad(f,x));
printf("(g(%f))^2=%f\n",x,Quad(g,x));
}
Exemplo 6.6.2. Faça um código para calcular
onde
Vamos começar construindo uma rotina que imprime os pesos e abscissas de
uma quadratura.
#include <stdio.h>
#include <math.h>
#define DEBUG
void boole(double a,double b,int N,double *nodes, double *weights)
{
int i;
for (i=0;i<N;i++)
{
nodes[i]=a+ (b-a)*i/(N-1.0);
}
weights[0]=(b-a)*28/90.0/(N-1.0);
for (i=1;i<N;i+=4)
{
weights[i]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+1]=4.0*12.0*(b-a)/90.0/(N-1.0);
weights[i+2]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+3]=4.0*7.0*(b-a)/45.0/(N-1.0);
}
weights[N-1]=28*(b-a)/90.0/(N-1.0);
}
void main (void)
{
int i,N=13;
if (N%4!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=1,x[N],w[N];
boole(a,b,N,x,w);
#ifdef DEBUG
for (i=0;i<N;i++)
{
printf("x[%d]=%f,w[%d]=%f\n",i,x[i],i,w[i]);
}
#endif
}
Agora vamos integrar algumas funções usando alocamento dinâmico de
memória.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void boole(double a,double b,int N,double *nodes, double *weights)
{
int i;
for (i=0;i<N;i++)
{
nodes[i]=a+(b-a)*i/(N-1.0);
}
weights[0]=(b-a)*28/90.0/(N-1.0);
for (i=1;i<N;i+=4)
{
weights[i]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+1]=4.0*12.0*(b-a)/90.0/(N-1.0);
weights[i+2]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+3]=4.0*7.0*(b-a)/45.0/(N-1.0);
}
weights[N-1]=28*(b-a)/90.0/(N-1.0);
}
void main (void)
{
int i,N=13;
if ((N%4)!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=1,*x,*w;
x=malloc(N*sizeof(double));
w=malloc(N*sizeof(double));
if ((x==NULL)||(w==NULL))
{
printf("erro ao alocar memória\n");
return;
}
boole(a,b,N,x,w);
//integral de 1 no intervalo [0,1];
double I=0;
for (i=0;i<N;i++) I+=w[i];
printf("A integral de 1 é %f\n",I);
//integral de x no intervalo [0,1];
I=0;
for (i=0;i<N;i++) I+=w[i]*x[i];
printf("A integral de x é %f\n",I);
//integral de x^2 no intervalo [0,1];
I=0;
for (i=0;i<N;i++) I+=w[i]*x[i]*x[i];
printf("A integral de x^2 é %f\n",I);
//integral de x^3 no intervalo [0,1];
I=0;
for (i=0;i<N;i++) I+=w[i]*x[i]*x[i]*x[i];
printf("A integral de x^3 é %f\n",I);
}
Ocorre que a integral está com um número fixo de pontos. Então, vamos
implementar rotinas que refinam até a convergência.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void boole(double a,double b,int N,double *nodes, double *weights)
{
int i;
for (i=0;i<N;i++)
{
nodes[i]=a+(b-a)*i/(N-1.0);
}
weights[0]=(b-a)*28/90.0/(N-1.0);
for (i=1;i<N;i+=4)
{
weights[i]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+1]=4.0*12.0*(b-a)/90.0/(N-1.0);
weights[i+2]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+3]=4.0*7.0*(b-a)/45.0/(N-1.0);
}
weights[N-1]=28*(b-a)/90.0/(N-1.0);
}
double f(double x)
{
return exp(-x);
}
void main (void)
{
int i,N=5;
if ((N%4)!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=1,*x,*w,tol=1e-10;
x=malloc(N*sizeof(double));
w=malloc(N*sizeof(double));
if ((x==NULL)||(w==NULL))
{
printf("erro ao alocar memória\n");
return;
}
boole(a,b,N,x,w);
//integral de 1 no intervalo [0,1];
int cont=0;
double I1=0,I2=0,erro;
for (i=0;i<N;i++) I1+=w[i]*f(x[i]);
do
{
cont++;
N=2*N-1;
x=realloc(x,N*sizeof(double));
w=realloc(w,N*sizeof(double));
boole(a,b,N,x,w);
I2=0;
for (i=0;i<N;i++) I2+=w[i]*f(x[i]);
erro=fabs(I2-I1);
printf("erro=%.12f\n",erro);
I1=I2;
}while (erro>tol);
printf("A integral de f(x) é %f e foi calculado com %d iterações\n",I2,cont);
}
Agora, vamos resolver o problema proposto, começando pela implementação
de :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void boole(double a,double b,int N,double *nodes, double *weights)
{
int i;
for (i=0;i<N;i++)
{
nodes[i]=a+(b-a)*i/(N-1.0);
}
weights[0]=(b-a)*28/90.0/(N-1.0);
for (i=1;i<N;i+=4)
{
weights[i]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+1]=4.0*12.0*(b-a)/90.0/(N-1.0);
weights[i+2]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+3]=4.0*7.0*(b-a)/45.0/(N-1.0);
}
weights[N-1]=28*(b-a)/90.0/(N-1.0);
}
double integrando(double tau, double *t)
{
return sin(*t-tau)*exp(-tau*tau);
}
double f(double t)
{
int i,N=5;
if ((N%4)!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=1,*x,*w,tol=1e-10;
x=malloc(N*sizeof(double));
w=malloc(N*sizeof(double));
if ((x==NULL)||(w==NULL))
{
printf("erro ao alocar memória\n");
return;
}
boole(a,b,N,x,w);
int cont=0;
double I1=0,I2=0,erro;
for (i=0;i<N;i++) I1+=w[i]*integrando(x[i],&t);
do
{
cont++;
N=2*N-1;
x=realloc(x,N*sizeof(double));
w=realloc(w,N*sizeof(double));
boole(a,b,N,x,w);
I2=0;
for (i=0;i<N;i++) I2+=w[i]*integrando(x[i],&t);
erro=fabs(I2-I1);
I1=I2;
}while (erro>tol);
return I2;
}
void main (void)
{
printf("f(1)=%f\n",f(1));
}
Agora, vamos fazer a última integral:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void boole(double a,double b,int N,double *nodes, double *weights)
{
int i;
for (i=0;i<N;i++)
{
nodes[i]=a+(b-a)*i/(N-1.0);
}
weights[0]=(b-a)*28/90.0/(N-1.0);
for (i=1;i<N;i+=4)
{
weights[i]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+1]=4.0*12.0*(b-a)/90.0/(N-1.0);
weights[i+2]=4.0*16.0*(b-a)/45.0/(N-1.0);
weights[i+3]=4.0*7.0*(b-a)/45.0/(N-1.0);
}
weights[N-1]=28*(b-a)/90.0/(N-1.0);
}
double integrando(double tau, double *t)
{
return sin(*t-tau)*exp(-tau*tau);
}
double f(double t)
{
int i,N=5;
if ((N%4)!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=t,*x,*w,tol=1e-10;
x=malloc(N*sizeof(double));
w=malloc(N*sizeof(double));
if ((x==NULL)||(w==NULL))
{
printf("erro ao alocar memória\n");
return;
}
boole(a,b,N,x,w);
int cont=0;
double I1=0,I2=0,erro;
for (i=0;i<N;i++) I1+=w[i]*integrando(x[i],&t);
do
{
cont++;
N=2*N-1;
x=realloc(x,N*sizeof(double));
w=realloc(w,N*sizeof(double));
boole(a,b,N,x,w);
I2=0;
for (i=0;i<N;i++) I2+=w[i]*integrando(x[i],&t);
erro=fabs(I2-I1);
I1=I2;
}while (erro>tol);
free(x);
free(w);
return I2;
}
void main (void)
{
int i,N=5;
if ((N%4)!=1)
{
printf("o número de pontos da quadratura deve ser da forma 4N+1\n");
return;
}
double a=0,b=1,*x,*w,tol=1e-10;
x=malloc(N*sizeof(double));
w=malloc(N*sizeof(double));
if ((x==NULL)||(w==NULL))
{
printf("erro ao alocar memória\n");
return;
}
boole(a,b,N,x,w);
int cont=0;
double I1=0,I2=0,erro;
for (i=0;i<N;i++) I1+=w[i]*f(x[i]);
do
{
cont++;
N=2*N-1;
x=realloc(x,N*sizeof(double));
w=realloc(w,N*sizeof(double));
boole(a,b,N,x,w);
I2=0;
for (i=0;i<N;i++) I2+=w[i]*f(x[i]);
erro=fabs(I2-I1);
I1=I2;
}while (erro>tol);
free(x);
free(w);
printf("O valor da integral é %f\n",I2);
}
Observe que existem várias linhas do código repetida. Isso pode ser
melhorado quando usamos ponteiro para função. Vamos calcular
com
essa ferramenta:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double Boole(double (*f)(double, double),double a,double b, int N,double *param)
{
int i;
double h=(b-a)/(4*N),Int=0,t=param[0];
Int=14./45.*(*f)(a,t);
for(i=0;i<N;i++)
{
Int+=64./45.*(*f)(a+h,t);
Int+=24./45.*(*f)(a+2*h,t);
Int+=64./45.*(*f)(a+3*h,t);
Int+=28./45.*(*f)(a+4*h,t);
a+=4*h;
}
Int-=14./45.*(*f)(a,t);
return h*Int;
}
double integrando(double tau, double t)
{
return sin(t-tau)*exp(-tau*tau);
}
void main(void)
{
double param[1]={1};
printf("f(1)=%f\n",Boole(integrando,0,1,5,param) );
}
Agora, vamos resolver o problema proposto:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double Boole(double (*f)(double, double),double a,double b, int N,double *param)
{
int i;
double h=(b-a)/(4*N),Int=0,t=param[0];
Int=14./45.*(*f)(a,t);
for(i=0;i<N;i++)
{
Int+=64./45.*(*f)(a+h,t);
Int+=24./45.*(*f)(a+2*h,t);
Int+=64./45.*(*f)(a+3*h,t);
Int+=28./45.*(*f)(a+4*h,t);
a+=4*h;
}
Int-=14./45.*(*f)(a,t);
return h*Int;
}
double integrando(double tau, double t)
{
return sin(t-tau)*exp(-tau*tau);
}
double f(double t,double tau)
{
int N=5;
double I1=0,I2=0,erro=0,a=0,b=t,tol=1e-10,param[1]={t};
I1=Boole(integrando,a,b,N,param);
int cont=0;
do
{
cont++;
N=2*N-1;
I2=Boole(integrando,a,b,N,param);
erro=fabs(I2-I1);
I1=I2;
}while (erro>tol);
return I2;
}
void main(void)
{
int N=5;
double I1=0,I2=0,erro=0,a=0,b=1,tol=1e-10,param[1]={0};
I1=Boole(f,a,b,N,param);
int cont=0;
do
{
cont++;
N=2*N-1;
I2=Boole(f,a,b,N,param);
erro=fabs(I2-I1);
I1=I2;
}while (erro>tol);
printf("O valor da integral é %f\n",I2);
}