%cabeçalho para todos os capítulos
%\input{cabecalho}

%\begin{document}

%Opções para o pacote listings
%\input{listingOptions}

\chapter{Mergulhando no ``while''}

\begin{center}
\shabox{
  \begin{Bitemize}
    \item[]\textbf{Quais novidades veremos nesta aula?}
    \item Reforço em \texttt{while}
    \item O comando \texttt{do...while}
  \end{Bitemize}
} % \shabox
\end{center}
\bigskip

\section {Um pouco mais sobre primos.}

Vamos iniciar este capítulo com dois exercícios. Primeiro, que tal
modificarmos o método de geração de primos para que ele use o fato de que
os únicos candidatos a primos maiores do que 2 são ímpares? Uma complicação
interessante é que o \texttt{limiteInferior} para o próximo primo pode ser
modificado pelo usuário a qualquer momento chamando
\texttt{carregaLimiteInferior}. Isso deve ser contemplado na solução. Aqui vai a
resposta:

\begin{lstlisting}
/**
 * A cada chamada, calcula um novo primo seguindo ordem crescente.
 */
int próximoPrimo()
{
  // Move o limite inferior na direção do próximo primo.
  // Temos que considerar que o limite inferior pode ser par
  // porque ele pode ser modificado a qualquer momento com uma
  // chamada a carregaLimiteInferior.
  if (limiteInferior == 1)
    limiteInferior = 2;
  else if (limiteInferior % 2 == 0)
    limiteInferior = limiteInferior + 1;
  else
    limiteInferior = limiteInferior + 2;

  // Encontra o próximo primo
  while (!éPrimo(limiteInferior))
    limiteInferior = limiteInferior + 2;

  return limiteInferior;
}
\end{lstlisting}

Nosso próximo desafio é criar uma nova classe \texttt{ManipuladorDeInteiros}. Ela
deve conter o método \texttt{fatoraInteiro} que deve imprimir a decomposição em
primos de um inteiro positivo maior ou igual a 2. Uma dica importante é
usar o \texttt{GeradorDePrimos} Antes de ler solução colocada abaixo, tente com
afinco fazer o exercício sozinho.

\begin{lstlisting}
class ManipuladorDeInteiros {
  /**
   * Fatora em primos um inteiro > 1.
   */
  void fatoraInteiro(int x)
  {
    System.out.print(x + " =");

    // Usa um gerador de primos para encontrar os primos menores ou iguais a x.
    GeradorDePrimos gerador = new GeradorDePrimos();
    int primo = gerador.próximoPrimo();

    // Continua fatorando o número até que x torne-se 1.
    while (x > 1)
    {
      if (x % primo == 0)
      {
        System.out.print(" " + primo);
        x = x / primo;
      }
      else
        primo = gerador.próximoPrimo();
    }

    // Imprime um fim de linha no final.
    System.out.println();
  }
}
\end{lstlisting}

Um exemplo de uso do nosso \texttt{ManipuladorDeInteiros}:

\begin{verbatim}
Welcome to DrJava.
> ManipuladorDeInteiros m = new ManipuladorDeInteiros()
> m.fatoraInteiro(5)
5 = 5
> m.fatoraInteiro(10)
10 = 2 5
> m.fatoraInteiro(18)
18 = 2 3 3
> m.fatoraInteiro(123456)
123456 = 2 2 2 2 2 2 3 643
> m.fatoraInteiro(12345678)
12345678 = 2 3 3 47 14593
> m.fatoraInteiro(167890)
167890 = 2 5 103 163
>
\end{verbatim}

Obs: Note que na solução usamos uma rotina de impressão nova:
\texttt{System.out.print}. Ela é muito parecida com
\texttt{System.out.println} com a diferença de que não muda a linha ao
terminar de imprimir.

\section{Uma biblioteca de funções matemáticas.}

Terminamos com um exercício clássico. Vamos mostrar como construir uma
pequena biblioteca de funções matemáticas avançadas. Com será que o
computador consegue calcular senos, cossenos, logaritmos? O segredo para
implementar essas funções em Java é um bom conhecimento de cálculo e
laços.

Usando cálculo, sabemos que essas funções matemáticas ``complicadas'' possuem
expansões de Taylor. Estas expansões envolvem apenas polinômios que podem ser
calculados facilmente usando laços. Pena que vocês só vão aprender isso na
disciplina de Cálculo mais para o fim do semestre. De qualquer forma,
vejamos a expansão de algumas dessas funções:

\begin{itemize}
  \item $sen(x) = \frac{x}{1!} - \frac{x^3}{3!} + \frac{x^5}{5!} - \ldots +
                  \frac{(-1)^{k} x^{(2k+1)}}{(2k+1)!} + \ldots$

  \item $cos(x) = 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} + \ldots +
                  \frac{(-1)^{k} x^{(2k)}}{(2k)!} + \ldots$

  \item $ln(1 + x) = x - \frac{x^2}{2} + \frac{x^3}{3} - \frac{x^4}{4} + \ldots +
                     \frac{(-1)^{(k - 1)} x^{k}}{k} + \ldots$

        Isso funciona bem sempre que $|x| < 1$.
\end{itemize}

O segredo para usar essas fórmulas no computador é continuar somando até
que o módulo do próximo termo seja muito pequeno e por isso possa ser
desprezado.

Antes de apresentarmos aqui a solução que consideramos ideal, faça com cuidado
e atenção os exercícios 1 (implementação das funções  \texttt{double
pot(double x, int y)} e \texttt{int fat(int x)}) e 2 (implementação da função 
 \texttt{double sen (double x)} usando as funções do exercício 1.
 
Agora, após termos feito, os exercícios 1 e 2, iremos criar uma nova classe,
que chamaremos \texttt{Matemática}, com métodos para calcular funções como as
apresentadas acima. Abaixo vemos a classe com uma função que calcula $sen(x)$
implementada. Compare esta forma de implementar com as formas usadas no
exercício. Qual é mais rápida? Qual é mais fácil de entender?

\begin{lstlisting}
class Matemática
{
  // Controla o significado de "pequeno".
  double epsilon = 1.0e-8;

  double sen(double x)
  {
    int k = 1;
    double termo = x;
    double seno = termo;
    while (termo*termo > epsilon*epsilon)
    {
      // É muito mais fácil construir o próximo termo usando o anterior.
      k = k + 2;
      termo = -termo * x * x / (k - 1) / k;
      seno = seno + termo;
    }
    return seno;
  }
}
\end{lstlisting}

Um exemplo de uso:

\begin{verbatim}
Welcome to DrJava.
> m = new Matemática();
> m.sen(0.3)
0.2955202066613839
> m.sen(0.5)
0.4794255386164159
> m.sen(3.141596/2.0)
0.9999999999925767
>
\end{verbatim}

\section{do...while}

Para complementar os laços possíveis em Java, vejamos uma pequena variação do
\texttt{while}. Nele a condição é testada sempre antes de execução do corpo de
comandos que compõe o laço. Já o laço \texttt{do...while} tem a condição
testada apenas no final. Conseqüentemente, no caso do \texttt{do...while},
existe a garantia que o conteúdo no interior do laço será executado pelo menos
uma vez, enquanto no \texttt{while} este pode nunca ser executado. Na prática,
a existência destes dois tipos de laços é uma mera conveniencia sintática, já
que um pode ser facilmente substituído pelo outro.

Vejamos um exemplo de utilização do \texttt{do...while}:

\begin{lstlisting}
int fatorial(int x)
{
  int resultado = 1;
  do
  {
    resultado = resultado * x;
    x = x - 1;
  } while (x > 1)
  return resultado;
}
\end{lstlisting}

\section{Exercícios}

\begin{enumerate}

\item Implementar na classe \texttt{Matemática} as funções \texttt{double
    pot(double x, int y)} que calcula $x^y$ e \texttt{int fat(int x)} que
  calcula $x!$.

\item Implementar na classe \texttt{Matemática} a função \texttt{double sen
    (double x)} utilizando-se das funções \texttt{double
    pot(double x, int y)} e \texttt{int fat(int x)} do item anterior.
  
\item Implementar na classe \texttt{Matemática} funções para calcular $cos(x)$
  e $ln(1+x)$. Note que para implementar o $ln(1+x)$ deve-se criar uma função
  \texttt{double ln(double x)} e no interior da função definir uma variável
  local \texttt{x2 = 1 - x} de modo que se possa calcular $ln(1+x2)$.
  
\item O enunciado deste exercício é bem mais complexo que a solução, por isso
  não tenha medo! Imagine um quadrado em um plano e uma reta paralela a um dos
  lados do quadrado: a projeção do quadrado sobre a reta tem exatamente o
  mesmo comprimento que o lado do quadrado. Imagine agora que este quadrado
  seja girado sobre o plano; a projeção do quadrado sobre a reta tem um novo
  tamanho. Crie uma classe Projetor que possua um método gira que aceite como
  parâmetro o número de graus que o quadrado deve girar em relação à sua
  posição anterior e imprima na tela o tamanho da projeção do quadrado sobre a
  reta. Note que se o usuário executar o método duas vezes, com os parâmetros
  ``22'' e ``35'', sua classe deve responder qual o tamanho da projeção para
  inclinações do quadrado de 22 e 57 graus.

\begin{itemize}
  
\item Escreva 3 soluções para este exercício: uma que você considere elegante
  e clara, uma com um único método e uma com o máximo número possível de
  métodos. Utilize os métodos \texttt{sen()} e \texttt{cos()} desenvolvidos
  neste capítulo.
\item Utilize agora os métodos \texttt{java.lang.Math.cos()} e
  \texttt{java.lang.Math.sin()} disponíveis na biblioteca Java, que calculam,
  respectivamente, o coseno e o seno do ângulo passado como parâmetro em
  radianos (graus * PI/180 = radianos). Compare os resultados com os obtidos
  com nossas implementações de \texttt{sen()} e \texttt{cos()}.

\end{itemize}

\end{enumerate}

%\end{document}

