Departamento de Ciência da Computação - IME - USP

MAC2166 Introdução à Computação

Prova 2


QUESTÃO 1

    Simule a execução do programa abaixo, destacando a sua saída. A saída do programa consiste de tudo que resulta dos comandos printf.
#include <stdio.h>

float f1(int *a, int b, int c) 
{
   float x;  
  
   *a = ((*a)*b+c)%10; 

   x = ((float)b+(*a)+1)/10;

   return x;
}

int f2(int a, int b) 
{
   int   c;
   float x;

   x = a;
   c = (x+b)/10;
   x = (x+b)/10;

   printf("3: c=%d x=%f\n", c, x);

   return c;
}

float f3(int a, float *x) 
{
   int   i,j;
   float y ;

   i = *x;
   j = f2(a,i)+2;
   y = *x/j;
   *x = a-y ;

   printf("4: a=%d i=%d j=%d *x=%f y=%f\n", a,i,j,*x,y);

   return 2*y;
}

int main() 
{
  int   nusp, a, b, c;
  float e;
  char  p, q;
  
  
  printf ("Digite o seu no. USP: ");
  /* a seguir, use o seu numero USP */
  scanf ("%d", &nusp);      
  printf ("nusp = %d\n", nusp);
  
  
  a = (nusp%5)+1;
  b = 10-a;
  c = (2*b+1)/4;      
  printf("1: a=%d b=%d c=%d\n", a, b, c);
  
  
  e = f1(&b,a,c);      
  printf("2: a=%d b=%d c=%d e=%f\n", a, b, c, e);
  
  
  a = (nusp%5)+1;
  e = 1.5;
  b = f3(a,&e);
  printf("5: a=%d b=%d e=%f\n", a, b, e);
  
  
  a = nusp/10;
  b = (a%5)+1;
  p = 'a';
  q = p+b;
  printf("6: a=%d b=%d p=%c q=%c\n", a, b, p, q);
  
  
  return 0;
}

SOLUÇÃO
A resposta depende do resto da divisão do seu número USP por 5. Teste com o seu no. USP e compare a resposta.

(0) nusp%5 == 0. Veja os 2 exemplos abaixo.

Digite o seu no. USP: 1234560
nusp = 1234560
1: a=1 b=9 c=4
2: a=1 b=3 c=4 e=0.500000
3: c=0 x=0.200000
4: a=1 i=1 j=2 *x=0.250000 y=0.750000
5: a=1 b=1 e=0.250000
6: a=123456 b=2 p=a q=c
Digite o seu no. USP: 1234565
nusp = 1234565
1: a=1 b=9 c=4
2: a=1 b=3 c=4 e=0.500000
3: c=0 x=0.200000
4: a=1 i=1 j=2 *x=0.250000 y=0.750000
5: a=1 b=1 e=0.250000
6: a=123456 b=2 p=a q=c

(1) nusp%5 == 1. Veja os 2 exemplos abaixo.

Digite o seu no. USP: 1234561
nusp = 1234561
1: a=2 b=8 c=4
2: a=2 b=0 c=4 e=0.300000
3: c=0 x=0.300000
4: a=2 i=1 j=2 *x=1.250000 y=0.750000
5: a=2 b=1 e=1.250000
6: a=123456 b=2 p=a q=c
Digite o seu no. USP: 1234566
nusp = 1234566
1: a=2 b=8 c=4
2: a=2 b=0 c=4 e=0.300000
3: c=0 x=0.300000
4: a=2 i=1 j=2 *x=1.250000 y=0.750000
5: a=2 b=1 e=1.250000
6: a=123456 b=2 p=a q=c

(2) nusp%5 == 2. Veja os 2 exemplos abaixo.

Digite o seu no. USP: 1234562
nusp = 1234562
1: a=3 b=7 c=3
2: a=3 b=4 c=3 e=0.800000
3: c=0 x=0.400000
4: a=3 i=1 j=2 *x=2.250000 y=0.750000
5: a=3 b=1 e=2.250000
6: a=123456 b=2 p=a q=c
Digite o seu no. USP: 1234567
nusp = 1234567
1: a=3 b=7 c=3
2: a=3 b=4 c=3 e=0.800000
3: c=0 x=0.400000
4: a=3 i=1 j=2 *x=2.250000 y=0.750000
5: a=3 b=1 e=2.250000
6: a=123456 b=2 p=a q=c

(3) nusp%5 == 3. Veja os 2 exemplos abaixo.

Digite o seu no. USP: 1234563
nusp = 1234563
1: a=4 b=6 c=3
2: a=4 b=7 c=3 e=1.200000
3: c=0 x=0.500000
4: a=4 i=1 j=2 *x=3.250000 y=0.750000
5: a=4 b=1 e=3.250000
6: a=123456 b=2 p=a q=c
Digite o seu no. USP: 1234568
nusp = 1234568
1: a=4 b=6 c=3
2: a=4 b=7 c=3 e=1.200000
3: c=0 x=0.500000
4: a=4 i=1 j=2 *x=3.250000 y=0.750000
5: a=4 b=1 e=3.250000
6: a=123456 b=2 p=a q=c

(4) nusp%5 == 4. Veja os 2 exemplos abaixo.

Digite o seu no. USP: 1234564
nusp = 1234564
1: a=5 b=5 c=2
2: a=5 b=7 c=2 e=1.300000
3: c=0 x=0.600000
4: a=5 i=1 j=2 *x=4.250000 y=0.750000
5: a=5 b=1 e=4.250000
6: a=123456 b=2 p=a q=c
Digite o seu no. USP: 1234569
nusp = 1234569
1: a=5 b=5 c=2
2: a=5 b=7 c=2 e=1.300000
3: c=0 x=0.600000
4: a=5 i=1 j=2 *x=4.250000 y=0.750000
5: a=5 b=1 e=4.250000
6: a=123456 b=2 p=a q=c

QUESTÃO 2

(a)  Escreva uma função de protótipo
float seno(float x);
que recebe como parâmetro um número real x, representando um ângulo em radianos, e devolve um valor aproximado de seno de x, através da série
sen(x) = x/1! - x3/3! + x5/5! - x7/7! + . . . + (-1)k × x2k+1/(2k+1)! + . . .
O valor aproximado deve incluir todos os termos até que
|(-1)k × x2k+1/(2k+1)!| &le 0.00001.
Inclua também na soma o último termo calculado.

SOLUÇÃO

/* 
 * SOLUCAO 1: curta e grossa
 *
 *   Esta solucao possui alguns printfs sobrando que exibem 
 * cada termo calculado da serie.
 *
 */
#define EPS  0.00001

float sen(float x)
{
  float senox; /* aproximacao do seno de x */
  float termo; /* termo da serie           */ 
  int   k;     /* controle do denominador em cada termo da serie */

  /* inicialize com o primero termo da serie */
  k     = 1;
  termo = x; 
  senox = x;

  /* ou:  while (termo > EPS || -termo > EPS) */
  while (termo < -EPS || EPS < termo)
    {
      /* calcule o proximo termo */
      k = k + 2;
      termo = -termo*x*x/(k*(k-1));

      /* atualize a aproximacao */
      senox = senox + termo;
    }

  return senox;
}
/* 
 * SOLUCAO 2: identica a anterior.
 *
 *   Usa uma variavel para determinar o sinal de cada termo.
 *
 *   Esta solucao possui alguns printfs sobrando que exibem 
 * cada termo calculado da serie.
 */
#define EPS  0.00001

float sen(float x)
{
  float senox; /* aproximacao do seno de x */
  float termo; /* termo da serie           */ 
  int   k;     /* fatorial no denominador em termo da serie */
  int   sinal; /* indica o sinal de cada termo (+1 ou -1)*/

  /* inicialize com o primero termo da serie */
  k     = 1;
  sinal = 1;
  termo = x; 
  senox = x;

  /* ou:  while (termo > EPS || -termo > EPS) */
  while (termo < -EPS || EPS < termo)
    {
      /* calcule o proximo termo */
      k     = k + 2;
      sinal = -sinal;
      termo = termo*x*x/(k*(k-1));

      /* atualize a aproximacao */
      senox = senox + sinal*termo;
    }

  return senox;
}
/*
 * SOLUCAO 3: usa funcoes auxiliares para calcular modulo, fatorial e
 *            potencia. 
 *
 *   Usa uma variavel para determinar o sinal de cada termo.
 *
 *   Esta solucao possui alguns printfs sobrando que exibem 
 * cada termo calculado da serie.
 */
#define EPS  0.00001

float modulo(float valor)
{
  float valorabsoluto;

  valorabsoluto = valor;
  if (valor < 0)
    {
      valorabsoluto = -valor;
    }

  return valorabsoluto;
}

int fatorial (int k)
{
  int kfat; /* armazenara k fatorial */
  int i;

  kfat = 1;
  for (i = 2; i <= k; i++)
    {
      kfat = kfat * i;
    }

  return kfat;
}

float potencia(float x, int k)
{
  float xk; /* armazenara x elevado a k */ 
  int   i;

  xk = 1;
  for (i = 0; i < k; i++)
    {
      xk = xk * x;
    }

  return xk;
}

float sen(float x)
{
  float senox; /* aproximacao do seno de x */ 
  float termo; /* termo da serie           */  
  int   k;     /* fatorial no denominador em termo da serie */ 
  int   sinal; /* indica o sinal de cada termo (+1 ou -1)*/ 

  /* inicialize com o primero termo da serie */ 
  k     = 1;
  sinal = 1;
  termo = x; 
  senox = x;

  while (modulo(termo) > EPS)
    {
      /* calcule o proximo termo */ 
      k     = k + 2;
      sinal = -sinal;
      termo = potencia(x,k)/fatorial(k);

      /* atualize a aproximacao */ 
      senox = senox + sinal*termo;
    }

  return senox;
}
/*
 * SOLUCAO 4: colocaremos aqui qualquer solução que virmos e que 
 *            seja essencialmente diferente da anterior.
 */

 

  (b)  Suponha que é dada uma função de protótipo

float raiz(float x);
que recebe como parâmetro um real x ≥ 0 e devolve a raiz quadrada de x.

   Escreva uma função de protótipo

void senocosseno(float x, float *seno, float *cosseno);
que recebe como parâmetro um real x, 0 ≤ x ≤ PI/2 e devolve em *seno e *cosseno os valores de seno e cosseno de x, respectivamente.

   A sua função deve usar obrigatoriamente a função sen do item (a), mesmo que você não a tenha feito. Para calcular o cosseno, utilize a relação fundamental da trigonometria sen2x + cos2x = 1.

OBS.: Não é necessário reescrever aqui nem os protótipos nem as funções sen e raiz.

SOLUÇÃO

/* 
 * SOLUCAO 1: 
 *
 *   Esta solucao usa duas variaveis extras.
 *
 */
void senocosseno(float x, float *seno, float *cosseno)
{
  float senox;
  float cossenox;

  senox    = sen(x);   
  cossenox = raiz(1 - senox*senox);

  *seno    = senox;
  *cosseno = cossenox;
}
/* 
 * SOLUCAO 2: 
 *
 *  Solucao sem as variaveis extras.
 *
 */
void senocosseno(float x, float *seno, float *cosseno)
{
  *seno    = sen(x);
  *cosseno = raiz(1 - sen(x)*sen(x));
}
/* 
 * SOLUCAO 3: 
 *
 *  Solucao sem as variaveis extras.
 *
 */
void senocosseno(float x, float *seno, float *cosseno)
{
  *seno    = sen(x);
  *cosseno = raiz(1 - *seno * *seno);
}

 

  (c)   Escreva uma programa que lê um número real x, 0 ≤ x ≤ PI/2, e imprime o seno e o cosseno de x. O seu programa deve, obrigatoriamente, utilizar a função do item (b) (mesmo que você não a tenha feito) para calcular o seno e o cosseno de x.

OBS.: Não é necessário reescrever aqui nem os protótipos nem as funções dos itens anteriores.

SOLUÇÃO

/* 
 * SOLUCAO 1: 
 *
 */
#include <stdio.h>

int main()
{
  float x;
  float senox;
  float cossenox;

  printf("Digite um angulo entre 0 e PI/2: ");
  scanf("%f",&x);

  senocosseno(x, &senox, &cossenox);
  printf("seno(%f)=%f cosseno(%f)=%f\n", x, senox, x, cossenox);

  return 0;
}

QUESTÃO 3

(a)  Escreva uma função de protótipo
float raizcub(float x);
que recebe como parâmetro um número real x ≥ 0 e devolve uma aproximação de raiz cúbica de x. Para x>0, uma aproximação pode ser obtida através da seqüência (r0,r1, . . . ,rn, . . .) onde r0= x e
rn+1 = (2rn+ x/rn2)/3
A aproximação a ser devolvida será o primeiro valor rn+1 para o qual |rn+1-rn| < 0.000001.

   Se sua função fizer verificação de igualdade entre dois números reais, deverá fazê-la usando a função de protótipo

int sao_iguais(float x, float y);
Não é necessário escrever a função sao_iguais.

SOLUÇÃO

/*
 * SOLUCAO 1: 
 *
 */
#define SIM 1
#define NAO 0

float raizcub(float x)
{
  float rant;
  float ratual;
  
  if (sao_iguais(x,0) == SIM)
    {
      rant   = 0;
      ratual = 0;
    }
  else
    {
      rant   = x;
      ratual = (2*x+1/x)/3;
    }

  /* ou: while (ratual-rant > EPS || rant-ratual > EPS) */
  while (ratual-rant < -EPS || EPS < ratual-rant) /* pode ser '<=' no lugar de '<' */
    {
      rant   = ratual;
      ratual = (2*rant + x/(rant*rant)) / 3;
    }

  return ratual;
}
/*
 * SOLUCAO 2: identica a SOLUCAO 1.
 *
 */
#define SIM 1
#define NAO 0

float raizcub(float x)
{
  float rant;
  float ratual;
  
  if (sao_iguais(x,0) == SIM)
    {
      rant   = 0;
      ratual = 0;
    }
  else
    {
      rant   = x;
      ratual = (2*x+1/x)/3;
    }

  /* ou: while (ratual-rant > EPS || rant-ratual > EPS) */
  while (ratual-rant < -EPS || EPS < ratual-rant) /* pode ser '<=' no lugar de '<' */
    {
      rant   = ratual;
      ratual = (2*rant + x/(rant*rant)) / 3;
    }

  return ratual;
}
/*
 * SOLUCAO 3: 
 *
 */
float raizcub(float x)
{
  float rant;
  float ratual;
  
  rant   = 0;
  ratual = x;
  /* ou: while (ratual-rant > EPS || rant-ratual > EPS) */
  while (ratual-rant < -EPS || EPS < ratual-rant) /* pode ser '<=' no lugar de '<' */
    {
      rant   = ratual;
      ratual = (2*rant + x/(rant*rant)) / 3;
    }

  return ratual;
}
/*
 * SOLUCAO 4: colocaremos aqui qualquer solução que virmos e que 
 *            seja essencialmente diferente da anterior.
 */

  (b)   Escreva um programa que lê dois números reais a e b, com 0 ≤ a ≤ b, e um inteiro k, com k>0 e imprime uma aproximação da área sob a função x1/3 no intervalo [a,b].

     O seu programa deve usar o método dos trapézios, como você fez no EP3.

OBS.: Não é necessário reescrever aqui nem o protótipo nem a função do item anterior.

SOLUÇÃO

/*
 * SOLUCAO 1: usa textualmente a formula no enunciado do EP3.
 *
 */
#include <stdio.h>

int main()
{
  float a, b;     /* limites do intervalo */
  int   k;        /* numero de trapezios  */
  float deltax;   /* altura de cada trapezio */
  float area;     /* aproximacao da area sob a funcao no intervalo [a,b] */
  int   i;       

  printf("Digite a, b e k: ");
  scanf("%f %f %d", &a, &b, &k);

  deltax = (b-a)/k;
  area = 0;
  for (i = 1; i <= k; i++)
    {
      area = area + ((raizcub(a+(i-1)*deltax)+raizcub(a+i*deltax)) * deltax) / 2;
    }

  printf("Area entre %f e %f = %f\n", a, b, area);

  return 0;
}
/*
 * SOLUCAO 2: simplifica um pouco a formula no enunciado do EP3.
 *
 */
#include <stdio.h>

int main()
{
  float a, b;     /* limites do intervalo */
  int   k;        /* numero de trapezios  */
  float deltax;   /* altura de cada trapezio */
  float area;     /* aproximacao da area sob a funcao no intervalo [a,b] */
  int   i;       

  printf("Digite a, b e k: ");
  scanf("%f %f %d", &a, &b, &k);

  deltax = (b-a)/k;
  area = 0;
  for (i = 1; i <= k; i++)
    {
      area = area + raizcub(a+(i-1)*deltax) + raizcub(a+i*deltax);
    }
  area = area*deltax/2;

  printf("Area entre %f e %f = %f\n", a, b, area);

  return 0;
}
/*
 * SOLUCAO 3: usa duas variaveis para determinar as abcissas das
 *            bases do trapezio e calcula explicitamente a
 *            area de cada trapezio.
 *
 */
#include <stdio.h>

int main()
{
  float a, b;     /* limites do intervalo */
  int   k;        /* numero de trapezios  */
  float deltax;   /* altura de cada trapezio */
  float area;     /* aproximacao da area sob a funcao no intervalo [a,b] */
  float xant;     /* abscissa de uma 'base' do trapezio */
  float xatual;   /* abscissa de uma 'base' do trapezio */
  float trapezio; /* area do trapezio */
  int   i;       

  printf("Digite a, b e k: ");
  scanf("%f %f %d", &a, &b, &k);

  deltax = (b-a)/k;
  xant   = a;
  area   = 0;
  for (i = 0; i < k; i++)
    {
      xatual = xant + deltax;

      /* calcule a area do proximo trapezio */
      trapezio = deltax * (raizcub(xant)+raizcub(xatual)) / 2; 
 
      /* atualize a aproximacao da area sob a funcao */
      area   = area + trapezio; 

      /* atualize a abcissa da nova 'base' */
      xant   = xatual;
    }

  printf("Area entre %f e %f = %f\n", a, b, area);

  return 0;
}
/*
 * SOLUCAO 4: identica a SOLUCAO 3.
 *            Nao usa variavel auxiliar para a area do trapezio.
 *
 */
#include <stdio.h>

int main()
{
  float a, b;     /* limites do intervalo */
  int   k;        /* numero de trapezios  */
  float deltax;   /* altura de cada trapezio */
  float area;     /* aproximacao da area sob a funcao no intervalo [a,b] */
  float xant;     /* abscissa de uma 'base' do trapezio */
  float xatual;   /* abscissa de uma 'base' do trapezio */
  int   i;       

  printf("Digite a, b e k: ");
  scanf("%f %f %d", &a, &b, &k);

  deltax = (b-a)/k;
  xant   = a;
  area   = 0;
  for (i = 0; i < k; i++)
    {
      xatual = xant + deltax;
      area   = area + deltax * (raizcub(xant)+raizcub(xatual))/2;  
      xant   = xatual;
    }

  printf("Area entre %f e %f = %f\n", a, b, area);

  return 0;
}
/*
 * SOLUCAO 5: usa duas variaveis para determinar as abcissas da
 *            base do trapezio e simplifica as contas.
 *
 */
#include <stdio.h>

int main()
{
  float a, b;     /* limites do intervalo */
  int   k;        /* numero de trapezios  */
  float deltax;   /* altura de cada trapezio */
  float area;     /* aproximacao da area sob a funcao no intervalo [a,b] */
  float xant;     /* abscissa de uma 'base' do trapezio */
  float xatual;   /* abscissa de uma 'base' do trapezio */
  int   i;       

  printf("Digite a, b e k: ");
  scanf("%f %f %d", &a, &b, &k);

  deltax = (b-a)/k;
  xant   = a;
  area   = (raizcub(a)+raizcub(b)) / 2;
  for (i = 1; i < k; i++)
    {
      xatual = xant + deltax;
      area   = area + raizcub(xatual);
      xant   = xatual;
    }

  area = area * deltax;

  printf("Area entre %f e %f = %f\n", a, b, area);

  return 0;
}

 

 

 


Last modified: Wed Apr 1 09:45:57 BRT 2009