




                                CAPTULO 5      
            
                                  FUNES    
            
                 O Pascal oferece muitas facilidades para a confeco de
            programas modularizados. A modularizao consiste na diviso
            de  um   programa   longo   em   vrias   partes,   chamadas
            subprogramas, cada uma funcionando de forma independente das
            outras, cada  uma realizando tarefas especficas controladas
            por um ncleo comum, chamado programa principal.
            
                             +--------------------------+
                             |   Programa   principal   |
                             +--------------------------+
                                ^          ^          ^
                               /           |           \
                              v            v            v
                     +------------+  +------------+ +------------+
                     | Subprogr_1 |  | Subprogr_2 | | Subprogr_3 |
                     +------------+  +------------+ +------------+
                                                          ^
                                                          |
                                                          v
                                                    +------------+
                                                    | Subprogr_4 |
                                                    +------------+
            
                 Cada subprograma  funciona como  se  fosse  um  pequeno
            programa,  com   suas  prprias   variveis,  suas  prprias
            definies de tipos, seus prprios subprogramas, etc.
                 Cada vez que um subprograma  chamado, ele  executado,
            e aps  o trmino  de sua  execuo, o  controle do programa
            volta ao  comando  que  vier  depois  do  ponto  de  onde  o
            subprograma foi chamado.
                 Em Pascal  podemos ter  subprogramas de  dois tipos: as
            funes (FUNCTIONS) e os procedimentos (PROCEDURES).
            
            5.1. ESTRUTURA DE UMA FUNO  
            
                 Uma funo   um  subprograma que tem um nico valor de
            retorno. O Pascal oferece muitas possibilidades na definio
            de funes. Uma funo  declarada na rea de declaraes do
            programa (depois  do cabealho e do USES e antes do BEGIN da
            seo principal) e possui a seguinte estrutura:
            
                 (1)  Um  cabealho  (ou  prottipo)  identificado  pela
            palavra chave  FUNCTION, seguida do nome da funo, da lista
            de parmetros  e tipos entre parnteses e separados entre si
            por vrgulas,  de um sinal de dois pontos e do tipo do valor
            que ser retornado pela funo.
                 Parmetros de  tipos diferentes devem ser separados por
            ponto-e-vrgula.
                 (2)  Uma  rea  de  declaraes  de  tipos,  variveis,
            constantes, rtulos, funes ou procedimentos.

                                        - 65 -





                 (3) A  definio da  funo delimitada  pelas  palavras
            chave BEGIN  e END, com um ponto-e-vrgula no final. O valor
            de retorno da funo  definida por  uma  atribuio do tipo
                           Nome_da_funo := Valor;
            
                 O valor  retornado por  uma funo  pode  ser  do  tipo
            inteiro, real,  boolean, pointer,  string,  char,  enumerado
            definido pelo usurio ou subtipos destes.
            
            Exemplo: O cabealho de uma funo F com parmetro x inteiro
            e  que retorne um valor inteiro (ou seja, F : Z ---> Z) deve
            ser declarado como
                           FUNCTION F (x: integer): integer;
                 Uma funo  G com  trs parmetros  a,  b,  c  do  tipo
            shortint e  que retorne  um valor  real, deve  ser declarada
            como
                      FUNCTION G (a, b, c: shortint): real;
                 No caso  da funo  F deste  exemplo, ela  ser chamada
            para ser  executada sempre  que  aparecer  no  programa  uma
            expresso do tipo F(expr), onde "expr"  qualquer constante,
            varivel ou  expresso do  tipo inteiro.  J a funo G, ela
            pode ser  chamada colocando-se em qualquer lugar do programa
            algo como  G(expr1, expr2,  expr3), onde  "expr1",  "expr2",
            "expr3" so expresso do tipo shortint.
            
            Exemplo: Neste  exemplo, definiremos  uma  funo  logaritmo
            decimal Log10(x) que, por definio, ser igual ao quociente
            Ln(x)/Ln(10).
                 Como queremos  que o  argumento x da funo seja sempre
            um nmero  real, ento  na  linha  do  cabealho  da  funo
            colocamos FUNCTION  Log10(x: real).  Para que ela retorne um
            valor real, finalizamos a linha do cabealho com " : real; "
            Dessa forma,  o cabealho  da funo  define seu  domnio  e
            contradomnio.
                 A seguir, entre os delimitadores BEGIN/END, definimos o
            valor que a funo deve retornar. Neste caso, a atribuio 
            feita ao nome da funo, e no ao nome seguido do parmetro.
            Uma atribuio como Log10(x) := Ln(x)/Ln(10) est errada.
            
                           FUNCTION Log10(x: real): real;
            
                           BEGIN
                             Log10 := Ln(x)/Ln(10);
                           END;
            
                 Uma verso  mais  elaborada,  deveria  verificar  se  o
            argumento x  vlido ou no. Temos ento:
            
            FUNCTION Log10(x: real): real; { versao 2 }
            
            BEGIN
              if (x < 0) then
              begin
                Writeln('Parametro invalido');

                                        - 66 -





                Halt; { encerra a execuo do programa }
              end
              else
                Log10 := Ln(x)/Ln(10);
            END;
            
                 Todo programa que queira usar essa funo LOG10, dever
            t-la definida na sua rea de declaraes:
            
            PROGRAM LogaritmoDecimal;
            
            FUNCTION Log10(x: real): real;
            
            BEGIN
              Log10 := Ln(x)/Ln(10);
            END; (* fim da definio da funo *)
            
            VAR
              num: real;
            
            BEGIN
              Write('Forneca um numero real positivo: '); Readln(num);
              Writeln('O logaritmo decimal de ',  num,  ' ' ',
                                                        Log10(num):8:4);
            END. (* fim do programa *)
            
            Exemplo:  Se   os  parmetros   da  funo  forem  de  tipos
            diferentes, ento  a lista  de parmetros  deve  separar  os
            tipos por ponto-e-vrgula. Por exemplo, uma funo TESTE que
            tenha os  parmetros x, y do tipo real e m, n do tipo word e
            que retorne  um  valor  do  tipo  longint  dever  ter  como
            cabealho:
            
                 FUNCTION Teste (x, y: real; m, n: word): longint;
            
                 Uma funo  F que  tenha parmetros a real, n inteiro e
            c1, c2,  c3 do  tipo char  e que  retorne um  string com  no
            mximo 20 caracteres dever ter como cabealho:
            
             FUNCTION F (a: real; n: integer; c1, c2, c3: char): Str20;
            
            onde Str20 deve ser um tipo definido em algum TYPE anterior:
            
                           TYPE Str20 = string[20];
            
                 No cabealho  de uma  funo no  permitido tipos como
            string[n].
            
            Exemplo: Neste  exemplo vamos  construir um programa que use
            duas funes: MAX(x, y) e MIN(x, y).
            
            PROGRAM MaxMin;
            
            FUNCTION Max(x, y: real): real;

                                        - 67 -





            
            (* Funo MAX ---> retorna o maior valor entre x e y *)
            
            BEGIN
              if (x >= y) then Max := x else Max := y;
            END; (* fim da definio de MAX *)
            
            FUNCTION Min(x, y: real): real;
            
            (* Funo MIN ---> retorna o menor valor entre x e y *)
            
            BEGIN
              if (x <= y) then Min := x else Min := y;
            END; (* fim da definio de MIN *)
            
            VAR
              a, b: real;
            
            BEGIN (* inicio do programa principal *)
              Write('Forneca dois numeros : '); Readln(a, b);
              Writeln('O maior dos dois ' ', Max(a, b):6:2);
              Writeln('e o menor ' ', Min(a, b):6:2)
            END. (* fim do programa *)
            
            OBSERVAO IMPORTANTE: As variveis definidas em uma funo,  
            chamadas variveis  locais, ou  as que  so  definidas  como
            parmetros, no  tm nenhuma  relao com  as  variveis  de
            outras funes  ou do  programa principal,  mesmo  que  elas
            tenham o mesmo nome.
                 O programa principal no tem conhecimento das variveis
            locais declaradas em uma funo.
            
            Exemplo: O  comando EXIT, quando usado em uma funo,  faz o
            controle do programa abandonar a funo e voltar ao ponto na
            qual a  funo foi  chamada.   til para  se interromper  a
            execuo de  uma funo  que foi chamada com algum argumento
            com valor invlido.
                 A seguir,  definimos uma  funo fatorial.  Se ela  for
            chamada com  argumentos invlidos  (negativos  ou  grandes),
            ento o  comando EXIT faz o controle do programa abandonar a
            funo e voltar ao ponto de chamada.
            
            FUNCTION Fat(n: shortint): longint;
            
            VAR           (* declarao das variveis locais *)
              i, prod_aux: longint;
            
            BEGIN
              if (n < 0) or (n > 12) then
              begin
                Writeln('Argumento n invalido na chamada de FAT.');
                EXIT; (* abandona a execuo da funo *)
              end
              else

                                        - 68 -





                if n <= 1 then
                  Fat := 1
                else
                begin
                  prod_aux := 1;
                  for i := 2 to n do
                    prod_aux := prod_aux * i;
                  Fat := prod_aux
                end;
            END; (* fim da definio da funo *)
            
                 Precisamos de  uma varivel  auxiliar  (prod_aux)  para
            guardar o  valor do  fatorial, porque  uma  atribuio  como
            Fat :=  Fat *  i no   permitida  (s seria possvel se Fat
            fosse uma varivel).
            
                 Um exemplo de um programa que use esta funo :
            
            PROGRAM UsandoFat;
            
            (* Lista os valores de n!, com 0 <= n <= 12 *)
            
            VAR
              i: shortint; (* este "i" no tem nenhuma relao com o "i"
                              da funo FAT *)
            
            (* Nesta rea, suponhamos que esteja escrita a FAT acima. *)
            
            BEGIN
              Writeln(' n            n!');
              for i := 0 to 12 do
                Writeln(i:2, Fat(i):12);
            END.
            
            Exemplo: Neste  exemplo definiremos  uma  funo  CURSO  que
            associa a alguns nmeros inteiros, nomes de cursos da UFPB.
            
                      FUNCTION Curso(n: byte): string;
            
                      BEGIN
                        CASE n OF
                          8  : Curso := 'Ciencias';
                          11 : Curso := 'Quim. Industrial';
                          22 : Curso := 'Eng. Civil';
                          23 : Curso := 'Eng. Alimentos';
                          24 : Curso := 'Eng. Mecanica';
                          25 : Curso := 'Bach. Quimica';
                          30 : Curso := 'Bach. Fisica';
                          32 : Curso := 'Bach. Matematica';
                          44 : Curso := 'Bach. Computacao';
                          else
                               Curso := 'Curso desconhecido';
                        END;
                      END;

                                        - 69 -





            
                 Suponhamos  que  esta  funo  esteja  definida  em  um
            arquivo  do   disco  chamado  CURSOS.PAS  (basta  digit-la,
            pressionar F2,  digitar CURSOS  e  pressionar  ENTER).  Para
            inclu-la em  qualquer programa  em Pascal,  basta usar  uma
            diretiva de incluso, cuja sintaxe ,
            
                           {$I NomeDoArquivo.Extensao}
            
                 Todo programa  que contiver  uma diretiva como essa, na
            hora em  que o  programa for compilado, o Pascal incluir no
            lugar da diretiva o referido arquivo.
                 Para que  uma diretiva  de incluso no seja confundida
            com um  comentrio, no deve haver espaos em branco entre a
            chave e o $I.
            
            PROGRAM CursosDaUFPB;
            
            {$I CURSOS.PAS} (* inclui o arquivo CURSOS.PAS *)
            
            VAR
              n: byte;
            
            BEGIN
              Write('Forneca o numero do curso: '); Readln(n);
              Writeln('---> O curso ', n, ' e '' ', Curso(n))
            END.
            
            Exemplo: Neste  exemplo, construiremos  uma funo  do  tipo
            string que, dado um inteiro n e um caracter x, ento o valor
            da funo no ponto (n, x) dever ser o caracter x repetido n
            vezes. Chamaremos a funo de REPETE.
                 Para as  variveis do  tipo string  est  definida  uma
            operao de soma, que na verdade  uma concatenao. Se X, Y
            so strings,  X + Y = string formado pela juno de X com Y.
            Por exemplo,  'Para' +  'iba' =  'Paraiba', '19'  +  '92'  =
            '1992', 'Jose' + 'Maria' = 'JoseMaria', etc.
                 Toda varivel  char, pode  ser considerada um string de
            comprimento 1. Assim, temos tambm, ' + 'B' = 'AB', etc.
                 Para repetir  o caracter  x por  n  vezes,  faremos  um
            somatrio de strings:
            
                           Str_aux := ''
                           Str_aux := '' + 'x' = 'x'        (n = 1)
                           Str_aux := 'x' + 'x' = 'xx'      (n = 2)
                           Str_aux := 'xx' + 'x' = 'xxx'    (n = 3)
                           Str_aux := 'xxx' + 'x' = 'xxxx'  (n = 4)
                           ...         ...        ...
            
            FUNCTION Repete(n: byte; x: char): string;
            
            VAR
              i: byte;
              Str_aux: string;

                                        - 70 -





            
            BEGIN
              Str_aux := '';
              for i := 1 to n do
                Str_aux := Str_aux + x;
              Repete := Str_aux;
            END;
            
                 Para uso  futuro, grave no disco esta funo sob o nome
            de REPETE.PAS.
                 Por exemplo, REPETE(6, '*') = '******', REPETE(10, '%')
            = '%%%%%%%%%%', REPETE(0, 'A') = '', etc.
                 Um exemplo de uso dessa funo :
            
            PROGRAM Testando_a_funcao_Repete;
            
            VAR
              i: byte;
              ch: char;
            
            {$I REPETE.PAS}
            
            BEGIN
              Write('Caracter a ser repetido? '); Readln(ch);
              Write('Quantidade de vezes? ');     Readln(i);
              Writeln;
              Writeln('REPETE (', i, ', ', ch, ') = ', Repete(i, ch))
            END.
            
                 Um outro exemplo, gera aleatoriamente os valores de i e
            ch  e   repete  esse   processo  indefinidamente   (at  ser
            pressionado as teclas CTRL e BREAK).
            
            PROGRAM Testando_a_funcao_Repete_2;
            
            USES
              Crt;
            
            VAR
              i: byte;
              ch: char;
            
            {$I REPETE.PAS}
            
            BEGIN
              Randomize;
              repeat
                i := Random(50); (* i  um inteiro qualquer de 0 a 49 *)
                ch := Chr(Random(255));
                Writeln;
                Writeln('REPETE (', i, ', ', ch, ') = ', Repete(i, ch));
                Delay(1000); (* pausa de 1 segundo *)
              until 1 > 2
            END.

                                        - 71 -





            
            Exemplo: O  conjunto de  funes  a  seguir,  complementa  a
            "deficincia"   do    Pascal   com    relao   s   funes
            trigonomtricas  e  hiperblicas.  Podem  ser  criados  dois
            arquivos no  disco TRIG.PAS e HIPER.PAS para serem includos
            em qualquer programa pela diretiva de incluso {$I TRIG.PAS}
            ou {$I HIPER.PAS}.
            
            { ======================================================== }
            {                   FUNCOES TRIGONOMETRICAS                }
            { ======================================================== }
            
            function Tg(x: real): real;      { Tangente     }
            
            begin
              if Cos(x) = 0 then Halt; { parametro invalido }
              Tg := Sin(x)/Cos(x)
            end;
            
            { -------------------------------------------------------- }
            
            function Cotg(x: real): real;    { Cotangente   }
            
            begin
              if Sin(x) = 0 then Halt; { parametro invalido }
              Cotg := Cos(x)/Sin(x)
            end;
            
            { -------------------------------------------------------- }
            
            function Sec(x: real): real;     { Secante      }
            
            begin
              if Cos(x) = 0 then Halt;
              Sec := 1/Cos(x)
            end;
            
            { -------------------------------------------------------- }
            
            function Cossec(x: real): real;  { Cossecante   }
            
            begin
              if Sin(x) = 0 then Halt;
              Cossec := 1/Sin(x)
            end;
            
            { -------------------------------------------------------- }
            
            function ArcSen(x: real): real;  { Arco-seno    }
            
            begin
              if (Abs(x) > 1) then
                Halt { parametro invalido }
              else

                                        - 72 -





                if (x = 1) then
                  ArcSen := Pi/2
                else
                  if (x = -1) then
                    ArcSen := -Pi/2
                  else
                    ArcSen := ArcTan(x/Sqrt(1 - Sqr(x)))
            end;
            
            { -------------------------------------------------------- }
            
            function ArcCos(x: real): real;  { Arco-cosseno }
            
            begin
              if (Abs(x) > 1) then
                Halt { parametro invalido }
              else
                if (x = 0) then
                  ArcCos := Pi/2
                else
                  if (x > 0) then
                    ArcCos := ArcTan(Sqrt(1 - Sqr(x))/x)
                  else
                    ArcCos := Pi + ArcTan(Sqrt(1 - Sqr(x))/x)
            end;
            
            { -------------------------------------------------------- }
            
            
            
            { ======================================================== }
            {                    FUNCOES HIPERBOLICAS                  }
            { ======================================================== }
            
            function Senh(x: real): real;    { Seno hiperbolico        }
            
            begin
              Senh := (Exp(x) - Exp(-x))/2
            end;
            
            { -------------------------------------------------------- }
            
            function Cosh(x: real): real;    { Cosseno hiperbolico     }
            
            begin
              Cosh := (Exp(x) + Exp(-x))/2
            end;
            
            { -------------------------------------------------------- }
            
            function Tgh(x: real): real;     { Tangente hiperbolica    }
            
            begin
              Tgh := (Exp(x) - Exp(-x))/(Exp(x) + Exp(-x))

                                        - 73 -





            end;
            
            { -------------------------------------------------------- }
            
            function ArcSenh(x: real): real; { Arco-seno hiperbolico   }
            
            begin
              ArcSenh := Ln(x + Sqrt(Sqr(x) + 1))
            end;
            
            { -------------------------------------------------------- }
            
            function ArcCosh(x: real): real; { Arco-cosseno hiperbolico}
            
            begin
              if (x < 1) then Halt; { parametro invalido }
              ArcCosh := Ln(x + Sqrt(Sqr(x) - 1))
            end;
            
            { -------------------------------------------------------- }
            
            function ArcTgh(x: real): real; { Arco-tangente hiperbolica}
            
            begin
              if (x >= 1) or (x <= -1) then Halt; { parametro invalido }
              ArcTgh := Ln((1 + x)/(1 - x))/2
            end;
            
            { -------------------------------------------------------- }
            
            
            Exemplo:  Definiremos  neste  exemplo  uma  funo  booleana
            chamada PRIMO(n)  que ser  TRUE se  n for  primo e FALSE em
            caso contrrio.
            
            FUNCTION Primo(n: longint): boolean;
            
            (*
                 Testa se um inteiro n  primo
            *)
            
            VAR
              i: word;
              raiz: real;
            
            BEGIN
              Primo := TRUE; (* suposio inicial de que n  primo *)
            
              if (n < 0) then n := -n;
              if (n = 2) then Exit;
              if (n = 1) or (n mod 2 = 0) then  (* caso em que n  1 *)
              begin                             (* ou  par > 2      *)
                Primo := FALSE;
                Exit;

                                        - 74 -





              end;
            
              raiz := Sqrt(n);        (* Caso geral: Se n for divis- *)
              i := 3;                 (* vel por um  mpar  maior  ou *)
              while (i <= raiz) do    (* igual a 3 e menor ou igual  *)
              begin                   (* raiz quadrada de n, ento  n *)
                if (n mod i = 0) then (* no  primo. Caso contrrio, *)
                begin                 (* n  primo.                   *)
                  Primo := false;
                  Exit;
                end;
                i := i + 2
              end
            END;
            
                 Gravando-se  esta   funo  no  disco  sob  o  nome  de
            PRIMO.PAS, podemos  usar o seguinte programa que lista todos
            os primos de 1 a 1000000:
            
            PROGRAM ListagemDePrimos;
            
            {$I PRIMO} (* ---> A extenso .PAS pode ser omitida *)
            
            VAR
              i: longint;
            
            BEGIN
              for i := 1 to 1000000 do
                if Primo(i) then Writeln(i:8, ' e'' primo.')
            END.
            
            
            Exemplo:  Vamos   construir  agora   nossa  funo  potncia
            POT(x, y) = x^y. Para uso posterior, vamos salv-la em disco
            sob o nome de POT.PAS.
                 Identificaremos com  0 todo nmero que, em mdulo, seja
            menor do que 10^-10.
            
            FUNCTION Pot(x, y: real): real;
            
            CONST
              epsilon = 1E-10;
            
            BEGIN
              if (Abs(x) < epsilon) and (Abs(y) < epsilon) then
              begin                      (* Caso em que x = 0 e y = 0 *)
                Writeln('ERRO: Forma indeterminada 0 elevado a 0.');
                Halt;
              end
              else
                if (Abs(x) < epsilon) then
                begin                         (* Caso em que x = 0    *)
                  if (y > 0) then
                    Pot := 0

                                        - 75 -





                  else
                  begin
                    Writeln('ERRO: Base nula e expoente negativo.');
                    Halt;
                  end
                end
                else
                  if (Abs(y) < epsilon) then  (* Caso em que y = 0    *)
                    Pot := 1
                  else
                    if (x > 0) then           (* Caso geral com x > 0 *)
                      Pot := Exp(y*Ln(x))
                    else                      (* Caso geral com x < 0 *)
                      if (Frac(y) > epsilon) and
                                       (1 - Frac(Abs(y)) > epsilon) then
                      begin
                        Writeln('ERRO: Base negativa e expoente ',
                                                        'fracionario.');
                        Halt;
                      end
                      else
                        if Odd(Round(y)) then   (* y impar, x < 0 *)
                          Pot := -Exp(y*Ln(-x))
                        else                    (* y par, x < 0   *)
                          Pot := Exp(y*Ln(-x));
            END;
            
                 A funo  POT assim  definida no   conveniente para o
            clculo de  razes. Como  exerccio, desenvolva  uma  funo
            Raiz(n, x) = raiz n-sima de x.
                 Como um programa-exemplo do uso de POT, temos:
            
            PROGRAM Potencias;
            
            {$I POT.PAS}
            
            VAR
              x, y: real;
            
            BEGIN
              repeat
                Write('x = '); Readln(x);
                Write('y = '); Readln(y);
                Writeln;
                Writeln('x^y = ', Pot(x, y):8:3);
                Writeln;
              until 1 > 2
            END.
            
            Exemplo: Vamos  elaborar agorar duas funes de parmetros e
            resultados inteiros: MDC(m, n), que calcula o mximo divisor
            comum de  m e  n, e MM que calcula o mnimo mltiplo comum
            de m e n.

                                        - 76 -





                 As funes  em Pascal podem depender, na sua definio,
            de outras funes previamente definidas. Ser o caso aqui da
            funo MMC que vamos defini-la dependendo de MDC:
            
                                           m*n
                           MMC(m, n) = -----------
                                        MDC(m, n)
            
            
            PROGRAM MdcMmc;
            
            (**********************************************************)
            (*          M.D.C.  E  M.M.C.  DE  DOIS  INTEIROS         *)
            (**********************************************************)
            
            FUNCTION MDC(m, n: longint): longint;
            
            (*              Maximo divisor comum de m e n             *)
            
            VAR
              q, r, auxiliar: longint;
            
            BEGIN
              if (m < n) then      (* Se m < n, ento os valores  de *)
              begin                (* m e n so trocados             *)
                auxiliar := m;
                m := n;
                n := auxiliar;
              end;
              repeat               (* m  dividido por n  sucessivas *)
                q := m div n;      (* vezes,  at  se  encontrar  um *)
                r := m mod n;      (* resto nulo. Aps cada diviso, *)
                m := n;            (* m    redefinido   como  sendo *)
                n := r;            (* igual  ao n anterior  e n como *)
              until (r = 0);       (* sendo o resto r anterior.      *)
              MDC := m
            END;
            
            (**********************************************************)
            
            FUNCTION MMC(m, n: longint): longint;
            
            (*                 Minimo multiplo comum                  *)
            
            BEGIN
              if (m = 0) or (n = 0) then
                Halt
              else
                MMC := (m*n) div MDC(m, n)
            END;
            
            (**********************************************************)
            
            

                                        - 77 -





            VAR
              a, b: longint;
            
            BEGIN
              Write('a? '); Readln(a);
              Write('b? '); Readln(b);
              Writeln('MDC(', a, ', ', b,') = ', MDC(a, b));
              Writeln('MMC(', a, ', ', b,') = ', MMC(a, b));
            END.
            
            
            Exemplo: Este ltimo exemplo desta seo, testa se um nmero
            inteiro positivo   potncia  de dois  ou no. Construmos a
            funo boolean  POTENCIADEDOIS(n) que   TRUE  se n  for uma
            potncia de  2 e   FALSE  em caso contrrio. Grave no disco
            esta  funo   sob  o  nome  de  POT_2.PAS  para  ser  usada
            futuramente.
                 O algoritmo usado foi o seguinte: so feitas sucessivas
            divises de  n por  2 at se encontrar um nmero mpar. Se o
            nmero mpar assim encontrado for 1, ento o n  potncia de
            2; caso contrrio, n no  potncia de 2.
            
            FUNCTION PotenciaDeDois(n: longint): boolean;
            
            VAR
              m: longint;
            
            BEGIN
              repeat
                m := n;
                n := n div 2;
              until n*2 <> m;
              if (m = 1) then
                PotenciaDeDois := true
              else
                PotenciaDeDois := false;
            END;
            
                 Como  exemplo  de  utilizao  dessa  funo,  temos  o
            programa abaixo que lista as potncias de 2 de 1 a 100000.
            
            PROGRAM Potencia_de_2;
            
            {$I POT_2}
            
            VAR
              x: longint;
            
            BEGIN
              for x := 1 to 100000 do
                if PotenciaDeDois(x) then
                  Writeln(x, ' e'' potencia de dois')
            END.
            

                                        - 78 -





            
            5.2. FUNES DEFINIDAS POR SOMATRIOS 
            
            Exemplo: A  funo real  FSERIE a  seguir   definida por um
            somatrio. Fornecidos  um real  x e a quantidade n de termos
            do somatrio, FSERIE(x, n)  definida como sendo o somatrio
            de SEN(kx)/k com k variando de 1 a n.
            
            FUNCTION FSerie(x: real; n: byte): real;
            
            (*
                                       Sen(2x)           Sen(nx)
              FSerie(x, n) = Sen(x) + --------- + ... + ---------
                                          2                 n
            *)
            
            var
              aux: real;
              k: byte;
            
            BEGIN
              aux := 0;
              for k := 1 to n do
                aux := aux + sin(k*x)/k;
              FSerie := aux
            END;
            
            
            Exemplo: A  funo a  seguir  uma aproximao para a funo
            exponencial de  base E. Trata-se da funo definida pelos 11
            primeiros termos da srie de Taylor de EXP(x).
                 Usamos  na   sua  definio   duas  funes   definidas
            anteriormente: FAT e POT.
            
            
            FUNCTION ExpAprox(x: real): real;
            
            (*                         2       3             10
                                      x       x             x
              ExpAprox(x) = 1 + x + ----- + -----  +  ... -----
                                      2!      3!           10!
            *)
            
            var
              i: byte;
              aux: real;
            
            BEGIN
              aux := 0;
              for i := 0 to 10 do
                aux := aux + Pot(x, i)/Fat(i);
              ExpAprox := aux
            END;
            

                                        - 79 -





            5.3. FUNES COMO PARMETROS DE OUTRAS FUNES     
            
                 O Pascal  permite  que  funes  usem  como  parmetros
            outras funes.  Assim   possvel  se  definir  funes  de
            funes. Para  se passar  uma funo como parmetro de outra
            funo so necessrios:
            
                 (1) Que  seja definido  o tipo de funo em um bloco de
            declaraes TYPE;
                 (2) Que  no incio  do programa  tenha  a  diretiva  de
            compilao {$F+}.
            
                 As funes  pr-definidas (SIN,  COS, LN,  etc.  )  no
            podem ser  passadas como parmetros. Nestes casos, o usurio
            poder definir  funes  equivalentes  a  essas  para  poder
            pass-las como  parmetros. Por exemplo, para poder passar o
            seno como  parmetro de  alguma outra  funo, uma soluo 
            definir a seguinte funo, e us-la ao invs de SIN:
            
                           FUNCTION Seno(x: real): real;
            
                           BEGIN
                             Seno := Sin(x)
                           END;
            
                 A declarao  do tipo  de funo  em um bloco TYPE deve
            ser feita na forma:
            
            TYPE
              NomeDoTipo = FUNCTION (Lista de parmetros e tipos) : Tipo
                                                    do Valor de retorno;
            
                 Por  exemplo,   para  se   declarar  um   tipo  chamado
            FuncaoDe2Variaveis,    que     corresponda     a     funes
             F : R^2 ---> R, temos o seguinte:
            
                 TYPE
                   FuncaoDe2Variaveis = FUNCTION(x, y: real): real;
            
            
            Exemplo: Este  exemplo mostra  como duas funes F e G podem
            ser passadas como parmetros para as funes DIF e COMPOSTA.
            
            
            PROGRAM FuncoesDeFuncoes;
            
            {$F+}
            
            TYPE           (* definio do tipo "funcao" *)
              funcao = FUNCTION(x: real): real;
            
            FUNCTION f(x: real): real;
            
            BEGIN

                                        - 80 -





              f := 5*x + 6;
            END;
            
            FUNCTION g(x: real): real;
            
            BEGIN
              g := Cos(2*x);
            END;
            
            FUNCTION Dif(p: funcao; a, b: real): real;
            
            BEGIN
              Dif := (p(a) - p(b))/(a - b)
            END;
            
            FUNCTION Composta(p, q: funcao; x: real): real;
            
            BEGIN
              Composta := p(q(x))
            END;
            
            VAR
              x0, y0: real;
            
            BEGIN
              x0 := 1; y0 := 2;
                                           (*        f(1) - f(2)  *)
              Writeln( Dif(f, x0, y0) );   (*  ---> ------------- *)
                                           (*           1 - 2     *)
            
                                               (* g(x0 - y0) - g(-5) *)
              Writeln( Dif(g, x0 - y0, -5) );  (* ------------------ *)
                                               (*  (x0 - y0) - (-5)  *)
            
              Writeln( Composta(f, g, 4) );    (* ---> f(g(4))  *)
            
              Writeln( Composta(g, f, x0) );   (* ---> g(f(x0)) *)
            END.
            
            
            Exemplo: A  funo a  seguir permite  o clculo de integrais
            definidas. A  integral da funo f no intervalo [a, b], pela
            Regra   do    Trapzio,       aproximadamente    igual    a
            d*(f(a) + f(b))/2 somado ao somatrio de d*f(a + i*d), com i
            variando de  1 a  n - 1,  e  d = (b - a)/n. n  a quantidade
            de subdivises  de [a,  b].  Quanto  maior  o  n,  melhor  a
            aproximao. Vamos  supor que  esta funo  est gravada  em
            disco em um arquivo de nome INTEGRAL.PAS.
            
            TYPE
              funcao = function(x: real): real;
            
            FUNCTION Integ(f: funcao; a, b: real): real;
            

                                        - 81 -





            (*
                           Integral de f  em  [a, b]
            *)
            
            CONST
              n = 1000; (* Quantidade   de   subdivisoes   de   [a, b].
                           Quanto maior n, melhor a aproximacao e maior
                           tempo gasto no calculo da integral *)
            
            VAR
              i: word;
              s, d: real;
            
            BEGIN
              d := (b - a)/n;
              s := 0;
              for i := 1 to n - 1 do
                s := s + d*f(a + i*d);
              Integ := s + d*(f(a) + f(b))/2
            END;
            
                 Um programa-exemplo do uso da funo Integ acima:
            
            PROGRAM IntegralDefinida;
            
            {$F+}
            
            {$I INTEGRAL}
            
            FUNCTION f(x: real): real;
            
            BEGIN
              f := 4/(x*x + 1);
            END; (* fim da definicao de f *)
            
            VAR
              a, b, int: real;
            
            BEGIN (* inicio da seo principal *)
              repeat
                Write('Forneca dois numeros reais A e B, com A < B : ');
                Readln(a, b);
              until a < b;
            
              int := Integ(f, a, b);
              Writeln('A integral de 4/(x*x + 1) em [A, B] ' ', int)
            
            END. (* fim do programa *)
            
            Um exemplo de execuo deste programa:
            
            Forneca dois numeros reais A e B, com A < B :  0  1
            A integral de 4/(x*x + 1) em [A, B]   3.1415924869E+00
            

                                        - 82 -





            Exemplo: Neste  exemplo, definimos a funo DERIV abaixo que
             uma aproximao para a derivada de f no ponto a.
            
            TYPE
              funcao = function(x: real): real;
            
            FUNCTION Deriv(f: funcao; a: real): real;
            
            (*
                            Derivada de f em x = a
            *)
            
            CONST
              h: real = 1E-10;
            
            BEGIN
              Deriv := (f(a + h) - f(a))/h;
            END;
            
                 Para melhorar  a aproximao  dos  resultados,  deve-se
            diminuir o valor de h. No entanto, para valores de h menores
            que esse, deve-se usar o tipo extended no lugar do real.
                 Supondo que  a funo  Deriv acima esteja em um arquivo
            chamado DERIV.PAS, temos o seguinte exemplo do uso dela:
            
            PROGRAM Derivada;
            
            {$F+}
            
            {$I DERIV}
            
            FUNCTION g(x: real): real;
            
            BEGIN
              g := LN(x)
            END;
            
            VAR
              x: real;
            
            BEGIN
              Write('Valor de x? '); Readln(x);
              Writeln;
              Writeln('A derivada de LN(x) em x = ', x:8:4, ' e'' ',
                                      Deriv(g, x):8:4);
            END.
            
                 Como exemplo de execuo deste programa, temos:
            
            Valor de x? 4
            
            A derivada de LN(x) em x =   4.0000 e'   0.2547
            

                                        - 83 -





            Exemplo: Neste  exemplo, construiremos  a funo CALCULARAIZ
            que determina uma raiz real da equao f(x) = 0 no intervalo
            [a, b], se f for contnua e f(a)*f(b) < 0.
                 O algoritmo usado na funo CalculaRaiz  o seguinte:
            (1) Calculamos o ponto mdio do intervalo MEDIO = (a + b)/2.
            (2) Se MEDIO for raiz de f(x) = 0, ento encerramos a funo
            atribuindo a CalculaRaiz o valor de MEDIO.
            (3) Se MEDIO no for raiz e se f(a)*f(MEDIO) < 0, ento isto
            significa que  a  raiz  procurada  est  entre  a  e  MEDIO.
            Renomeamos  b   de  MEDIO   e  voltamos  ao  passo  (1).  Se
            f(a)*f(MEDIO) > 0, ento a raiz procurada est entre Medio e
            b e,  devido a  isso, renomeamos  a de  MEDIO e  voltamos ao
            passo (1).
            (4) O processo deve se encerrar em (2) ou quando o intervalo
            [a, b],  aps  vrias  renomeaes  de  a  e  b,  ficar  com
            comprimento menor  que  um  epsilon  desejado.  Nesse  caso,
            dizemos que MEDIO  a raiz procurada.
            
            TYPE
              funcao = FUNCTION(x: real): real;
            
            FUNCTION CalculaRaiz(f: funcao; a, b: real): real;
            
            (*
               Determina uma raiz de f(x) = 0 em [a, b] se f(a)*f(b) < 0
            *)
            
            CONST
              epsilon = 1E-10;
            
            VAR
              medio: real;
            
            BEGIN
              if f(a)*f(b) >= 0 then Halt;
            
              repeat
                medio := (a + b)/2;
                if Abs(f(medio)) < epsilon then
                begin
                  CalculaRaiz := medio;
                  Exit;
                end
                else
                  if f(a)*f(medio) < 0 then
                    b := medio
                  else
                    a := medio;
              until Abs(a - b) < epsilon
            END;
            
                 Gravando  no   disco  esta   funo  com   o  nome   de
            CALCRAIZ.PAS, podemos executar o seguinte programa:
            

                                        - 84 -





            PROGRAM Calc_de_uma_raiz_real;
            
            {$F+}
            
            {$I CalcRaiz}
            
            FUNCTION f(x: real): real;
            
            BEGIN                        (*          2   x  *)
              f := x*x - Exp(x*Ln(2))    (*  f(x) = x - 2   *)
            END;
            
            VAR
              a, b: real;
            
            BEGIN
              Writeln('                      2   x');
              Writeln('Resolucao da equacao x = 2 , com A <= x <= B.');
              Writeln;
              Write('Valor de A? '); Readln(a);
              Write('Valor de B? '); Readln(b);
              Writeln;
              Writeln('A solucao procurada e'' ',
                                            CalculaRaiz(f, a, b):15:10);
            END.
            
                 Um exemplo de execuo desse programa:
            
                                  2   x
            Resolucao da equacao x = 2 , com A <= x <= B.
            
            Valor de A? -2
            Valor de B?  0
            
            A solucao procurada e'   -0.7666646959
            
            
            Exemplo: No  ltimo exemplo  deste captulo,  vamos elaborar
            uma funo  que d  uma estimativa  para o  ponto em que uma
            funo f  assume seu mximo. Calculando o ponto de mximo de
            -f, temos tambm o ponto de mnimo de f.
                 Usamos o seguinte:
                 (1) Inicialmente   feita  uma aproximao grosseira do
            ponto de  mximo de f. Isto  feito dividindo-se o intervalo
            [a, b]  em n  partes e  avaliando-se o  valor de  f em  cada
            subdiviso. O  maior valor  encontrado  ser  considerado  a
            primeira aproximao para o mximo de f.
                 (2) Concentrando-se  em torno  do valor  encontrado  em
            (1), dividimos  novamente o  intervalo em  partes menores  e
            encontramos uma  melhor  e  definitiva  aproximao  para  o
            mximo de f.
                 Definimos uma  funo chamada  MAXINICIAL  "dentro"  da
            definio da  funo MAXF.  Ela poderia  ter  sido  definida
            fora. Escrevemos  assim  apenas  para  mostrar  que  isso  

                                        - 85 -





            possvel. Neste  caso, a  nica parte  do programa  que  tem
            conhecimento da existncia de MAXINICIAL  a funo MAXF.
            
            
            TYPE
              funcao = function(x: real): real;
            
            FUNCTION MaxF(f: funcao; a, b: real): real;
            
            (*
                               Maximo de f em [a,b]
            *)
            
            FUNCTION MaxInicial(f: funcao; x1, x2, d: real): real;
            
            VAR
              vm, y, ValorMax: real;
            
            BEGIN    (* Inicio de MAXINICIAL *)
              y := x1;
              vm := y; ValorMax := f(vm); (*    Inicialmente, supomos *)
              while (y <= x2) do          (* que o  valor maximo de f *)
              begin                       (*  atingido em VM.        *)
                if (ValorMax < f(y)) then (*    A seguir,  comparamos *)
                begin                     (* f(VM)  com   cada  f(y), *)
                  vm := y;                (* onde y <= x2  incremen- *)
                  ValorMax := f(vm);      (* tado de D em D unidades. *)
                end;                      (* Sempre que f(VM) < f(y), *)
                y := y + d;               (* renomeamos  VM de y.  No *)
              end;                        (* final  das  comparaes, *)
              MaxInicial := vm;           (* VM ser ponto de maximo. *)
            END;     (* Fim de MAXINICIAL *)
            
            CONST
              delta = 0.01; (* Comprimento das subdivises de [a, b] *)
            
            VAR
              MaxAux: real;
            
            BEGIN    (* Incio de MAXF *)
            
              MaxAux := MaxInicial(f, a, b, delta);     (* Estimativa *)
                             (* grosseira para o ponto de mximo de f *)
            
              MaxF := MaxInicial(f, MaxAux - delta, MaxAux + delta,
                      delta/1000);      (* Estimativa do valor maximo *)
                                        (* mais refinada              *)
            END;     (* Fim de MAXF *)
            
                 So feitas  (b -  a)/delta +  2000 =  100(b - a) + 2000
            comparaes para  se determinar o mximo de f. "Salvando-se"
            a funo  MAXF acima  (juntamente com  o TYPE) em um arquivo
            chamado MAX.PAS, temos mais o seguinte exemplo:
            

                                        - 86 -





            
            PROGRAM MaxMin;
            
            {$F+}
            
            {$I Max}
            
            VAR
              a, b, Xmax, Xmin: real;
            
            FUNCTION f(x: real): real;
            
            BEGIN
              f := x*x*x - 12*x + 7
            END; (* fim da definio de f *)
            
            FUNCTION g(x: real): real;
            
            BEGIN
              g := -f(x)
            END; (* fim da definio de g *)
            
            BEGIN (* inicio do programa principal *)
              Writeln;
              Writeln('                           3');
              Writeln('MAXIMO E MINIMO DE f(x) = x - 12x +7 EM [a, b]');
              Writeln;
              Write('a = '); Readln(a);
              Write('b = '); Readln(b);
              Writeln;
            
              Xmax := MaxF(f, a, b);
              Xmin := MaxF(g, a, b);
            
              Writeln('O valor maximo de f e'' ', f(Xmax):8:4,
                                         ' e ocorre em x = ', Xmax:8:4);
              Writeln('O valor minimo de f e'' ', f(Xmin):8:4,
                                         ' e ocorre em x = ', Xmin:8:4);
            END. (* fim do programa *)
            
            
                 Executando-se este programa com [a, b] = [-3, 3], vemos
            as seguintes mensagens na tela:
            
                                       3
            MAXIMO E MINIMO DE f(x) = x - 12x +7 EM [a, b]
            
            a = -3
            b = 3
            
            O valor maximo de f e'  23.0000 e ocorre em x =  -2.0000
            O valor minimo de f e'  -9.0000 e ocorre em x =   2.0000
            
            

                                        - 87 -





            5.4. EXERCCIOS       
            
            
            1) Defina as seguintes funes:
            
               a) Multiplo(n, p) do tipo booleano que seja TRUE quando o
            inteiro n  for  mltiplo  do  inteiro  p  e  FALSE  em  caso
            contrrio.
                 A   funo    MULTIPLO   generaliza   a   funo   ODD:
            Odd(n) = NOT Multiplo(n, 2).
                                    m!
               b) Bin(m, n) = ------------- , m >= n >= 0, m, n inteiros
                               (m - n)! n!
            
               c) QDiv(n) = quantidade de divisores positivos do inteiro
            positivo n.
            
                d)  Distancia(x, y) = quantidade de caracteres respecti-
            vamente distintos  nos strings x e y, que devem ser do mesmo
            tamanho. Por exemplo, Distancia('UFPB', 'UFRN')= 2.
            
                e)  Inverso(x) = string x escrito ao contrrio. Exemplo:
            Inverso('Pascal') = 'lacsaP'.
            
                f)  Retira(Ch, Str)  = string  formado pela  retirada de
            todos  os   caracteres  Ch   do  string  Str.  Por  exemplo,
            Retira('e', 'Teste') = 'Tst', Retira('a', 'Teste') = 'Teste'
            
            
            2) Defina  uma funo  DParcial que  calcule aproximadamente
            derivadas parciais  de uma  funo em  um  ponto  dado.  Sua
            sintaxe dever ser:
            
            DParcial(f, coord,  a, b)  = derivada  de f  com  relao  
            coordenada coord  no ponto  (a, b).  a, b so reais, f  uma
            funo de RS02T em R e coord = 1 ou 2.
            
            
            3) Na  tabela  ASCII,  as  letras  maisculas  esto  a  uma
            distncia constante  e igual  a 32  das  respectivas  letras
            minsculas. Por  exemplo, Ord('A')  = 65  e Ord('a')  = 97 =
            65 +  32, Ord('W')  = 87 e Ord('w') = 119 = 87 + 32. Baseado
            nesta  informao,  construa  duas  funes  MAIUSCULA(x)  e
            MINUSCULA(x) que  sejam, respectivamente, o string x escrito
            em  letras   maisculas  e   em  minsculas.   Por  exemplo,
            Maiuscula('Dep. de  Matematica')  =  'DEP.  DE  MATEMATICA',
            Minuscula('DATA = 21/12/91') = 'data = 21/12/91'.
            
            
            4) Dados  os inteiros a, b e n, com 0 <= n <= 12, elabore um
            programa que desenvolva o binmio (ax + by)^n.
            (Sugesto: use as funes POT(x, y) e BIN(m, n) anteriores.)
            
            

                                        - 88 -
