Use o botão abaixo para reportar erros ou dar sugestões.

Computação Científica - Um Livro Colaborativo

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 ∫ 01f(t)dt,

onde f(t) = ∫ 0t sen (t − τ)e−τ2 dτ.

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 f(t):

#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 f(1) 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);  
}

Creative Commons License Este texto é disponibilizado nos termos da licença Creative Commons Atribuição-CompartilhaIgual 3.0 Não Adaptada (CC-BY-SA 3.0). Página gerada em 19/8/2020 às 17:33:16.

Informe erros ou edite você mesmo!