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

%\begin{document}

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

\chapter{Expressões e Variáveis Lógicas}

\begin{center}
\shabox{
  \begin{Bitemize}
    \item[]\textbf{Quais novidades veremos nesta aula?}
    \item Condições como expressões lógicas
    \item Variáveis booleanas
    \item Condições compostas e operadores lógicos: \texttt{\&\&}, \texttt{||}
    e \texttt{!}
    \item Precedência de Operadores
    \end{Bitemize}
} % \shabox
\end{center}
\bigskip

\section{Condições como expressões}

Já vimos que em Java, e outras linguagens de programação, as condições
exercem um papel fundamental. São elas que permitem que diferentes ações
sejam tomadas de acordo com o contexto. Isso é feito através dos
comandos \texttt{if} e \texttt{while}.

Mas, o que são condições realmente? Vimos apenas que elas consistem
geralmente de comparações, usando os operadores \texttt{==}, \texttt{>=}, \texttt{<=},
\texttt{>}, \texttt{<} e \texttt{!=}, entre variáveis e/ou constantes. Uma característica
interessante em linguagens de programação é que as condições são na verdades expressões
que resultam em verdadeiro ou falso. Vamos ver isso no DrJava:

\begin{verbatim}
Welcome to DrJava.
> 2 > 3
false
> 3 > 2
true
> int a = 2
> a == 2
true
> a >= 2
true
> a < a + 1
true
>
\end{verbatim}

Vejam que cada vez que digitamos uma condição o DrJava responde true
(para verdadeiro) ou false (para falso).

Para entender bem o que ocorre, é melhor imaginar que em Java as
condições são expressões que resultam em um dos dois valores lógicos:
``verdadeiro'' ou ``falso''. Neste sentido, Java também permite o uso de
variáveis para guardar os resultados destas contas, como vemos abaixo.

\begin{verbatim}
> boolean comp1 = 2 > 3
> comp1
false
> boolean comp2 = a < a + 1
> comp2
true
>
\end{verbatim}

Com isso acabamos de introduzir mais um tipo de variáveis, somando-se aos
tipos \texttt{int} e \texttt{double} já conhecidos: o tipo \texttt{boolean},
que é usado em variáveis que visam conter apenas os valores booleanos (verdadeiro
ou falso). Em português este tipo de variável é chamada de variável
\emph{booleana} em homenagem ao matemático inglês George Boole (1815-1864).

Agora que começamos a ver as comparações como expressões que calculam
valores booleanos, torna-se mais natural a introdução dos operadores
lógicos. Nós todos já estamos bem acostumados a condições compostas.
Algo como ``eu só vou à praia se tiver sol \emph{e} as ondas estiverem boas''.
Nesta sentença a conjução \emph{e} une as duas condições em uma nova condição
composta que é verdadeira somente se as duas condições que a formam forem
verdadeiras.

Em Java o ``\emph{e}'' lógico é representado pelo estranho símbolo
\texttt{\&\&}. Ou seja, uma condição do tipo \texttt{1 <= a <= 10} seria
escrita em Java como \texttt{a >= 1 \&\& a <= 10}.  Da mesma forma temos um
símbolo para o \emph{ou} lógico. Ele é o símbolo \texttt{||}. Isso mesmo, duas
barras verticais. Por fim, o símbolo \texttt{!} antes de uma expressão lógica
nega o seu valor. Por exemplo a condição "a não é igual a 0" poderia ser
escrita em Java como \texttt{!(a == 0)}\footnote{Daí vem a explicação para o
fato do sinal de diferente fazer referência ao ponto de exclamação.}.

Por fim, podemos montar expressões compostas unindo, através dos
operadores descritos acima, condições simples ou respostas de expressões
lógicas anteriores que foram armazenadas em variáveis boolenas. Mais uma
vez um exemplo vale mais que mil palavras.

\begin{verbatim}
Welcome to DrJava.
> (2 > 3) || (2 > 1)
true
> boolean comp1 = 2 > 3
> comp1
false
> comp1 && (5 > 0)
false
> !(comp1 && (5 > 0))
true
> int a = 10
> (a > 5) && (!comp1)
true
> boolean comp2 = (a > 5) && comp1
> comp2
false
>
\end{verbatim}

Também podemos ``misturar'' operadores aritméticos e lógicos, sempre que
isso faça sentido. Por exemplo

\begin{verbatim}
> (a - 10) > 5
false
> a - (10 > 5)
koala.dynamicjava.interpreter.error.ExecutionError: Bad type in subtraction
>
\end{verbatim}

Note que a última expressão resultou em um erro. Afinal de contas, ela
pede para somar, a uma variável inteira, o resultado de uma expressão
lógica, misturando tipos. Isto não faria sentido em Java.

Outra coisa que pode ser feita é a criação de métodos que devolvem um
resultado lógico. Assim a resposta dada por esses métodos pode ser usada
em qualquer lugar onde uma condição faça sentido, como um \texttt{if} ou um \texttt{while}.
Por exemplo, se alterarmos o método \texttt{verificaPrimalidade}, dado na aula
passada, para devolver a resposta (se o número é primo ou não), ao invés
de imprimir na tela, teríamos o seguinte método \texttt{éPrimo}:

\begin{lstlisting}
/**
 * Verifica se um número inteiro positivo é primo ou não.
 */
boolean ÉPrimo(int x)
{
  // Todos os números inteiros positivos sao divisíveis por 1.
  int númeroDeDivisores = 1;
  // O primeiro candidato a divisor não trivial é o 2.
  int candidatoADivisor = 2;

  // Testa a divisão por todos os números menores ou iguais a x.
  while (candidatoADivisor <= x)
  {
    if (x % candidatoADivisor == 0)
      númeroDeDivisores = númeroDeDivisores + 1;
    candidatoADivisor = candidatoADivisor + 1;
  }

  if (númeroDeDivisores == 2)
    return true;
  else
    return false;
}
\end{lstlisting}

\section{Precedência}

Como acabamos de apresentar vários operadores novos, devemos estabelecer
a precedência entre eles. Lembre que já conhecemos as regras de
precedência dos operadores aritméticos há muito tempo. Já a precedência
dos operadores lógicos é coisa nova. A tabela abaixo apresenta todos os
operadores vistos em aula, listados da precedência mais alta (aquilo que
deve ser executado antes) à mais baixa:

\medskip
\begin{center}
\begin{tabular}{|l|c|}
\hline
operadores unários & - ! \\
\hline
operadores multiplicativos & * / \% \\
\hline
operadores aditivos & + - \\
\hline
operadores de comparação & == != > < >= <= \\
\hline
``\emph{e}'' lógico & \&\& \\
\hline
``\emph{ou}'' lógico & || \\
\hline
atribuição & = \\
\hline
\end{tabular}
\end{center}
\medskip

Entre operadores com mesma precedência a operações são computadas da
esquerda para a direita.

Note porém que, nos exemplos acima, abusamos dos parênteses mesmo quando, de
acordo com a tabela de precedência, eles são desnecessários.  Sempre é bom
usar parênteses no caso de expressões lógicas (ou mistas), pois a maioria das
pessoas não consegue decorar a tabela acima. Assim, mesmo que você tenha uma
ótima memória, o seu código torna-se mais legível para a maioria dos mortais.


\section{Exemplos}

Primeiro, vamos retomar o método \texttt{verificaLados} da classe
\texttt{TianguloRetangulo3} vista no Capítulo 6. Nele, testamos se não há lado de
comprimento nulo. Entretanto, parece mais natural e correto forçar todos
os lados a terem comprimento estritamente positivo:

\begin{lstlisting}
if ((a > 0) && (b > 0) && (c > 0))
{
  // Aqui vão os comandos para verificar a condição pitagórica.
}
\end{lstlisting}

Podemos também usar condições compostas para escrever uma versão mais
rápida do método \\ \texttt{ÉPrimo} da aula passada.

\begin{lstlisting}
/**
 * Verifica se um número inteiro positivo é primo ou não.
 */
boolean ÉPrimo(int x)
{
  // Todos os números inteiros positivos sao divisíveis por 1.
  int númeroDeDivisores = 1;
  // O primeiro candidato a divisor não trivial é o 2.
  int candidatoADivisor = 2;

  // Testa a divisão por todos os números menores ou iguais a x/2 ou
  // até encontrar o primeiro divisor.
  while ((candidatoADivisor <= x/2) && (númeroDeDivisores == 1))
  {
    if (x % candidatoADivisor == 0)
      númeroDeDivisores = númeroDeDivisores + 1;
    candidatoADivisor = candidatoADivisor + 1;
  }

  if ((númeroDeDivisores == 1) && (x != 1) && (x != 0) && (x != -1))
    return true;
  else
    return false;
}
\end{lstlisting}

Melhor ainda podemos finalmente escrever a classe \texttt{GeradorDePrimos} de
forma completa. O método mais interessante é o \texttt{próximoPrimo} que
devolve o primeiro número primo maior do que o último gerado. Este
exemplo já é bem sofisticado, vocês terão que estudá-lo com calma. 
Uma sugestão: tente enteder o que o programa faz, um método por vez. O único
método mais complicado é o \texttt{ÉPrimo}, mas este nós já vimos.

\begin{lstlisting}
class GeradorDePrimos
{
  // Limite inferior para busca de um novo primo.
  int limiteInferior = 1;

  /**
   * Permite mudar o limite para cômputo do próximo primo.
   */
  void carregaLimiteInferior(int l)
  {
    limiteInferior = l;
  }

  /**
   * Verifica se um número inteiro positivo é primo ou não.
   */
  boolean ÉPrimo(int x)
  {
    // Todos os números inteiros positivos sao divisíveis por 1.
    int númeroDeDivisores = 1;
    // O primeiro candidato a divisor não trivial é o 2.
    int candidatoADivisor = 2;

    // Testa a divisão por todos os números menores ou iguais a x/2 ou
    // até encontrar o primeiro divisor.
    while ((candidatoADivisor <= x/2) && (númeroDeDivisores == 1))
    {
      if (x % candidatoADivisor == 0)
        númeroDeDivisores = númeroDeDivisores + 1;
      candidatoADivisor = candidatoADivisor + 1;
    }

    if ((númeroDeDivisores == 1) && (x != 1) && (x != 0) && (x != -1))
      return true;
    else
      return false;
  }

  /**
   * A cada chamada, calcula um novo primo seguindo ordem crescente.
   */
  int próximoPrimo()
  {
    // Busca o primeiro primo depois do limite.
    limiteInferior = limiteInferior + 1;
    while (!ÉPrimo(limiteInferior))
      limiteInferior = limiteInferior + 1;

    return limiteInferior;
  }
}
\end{lstlisting}

Não deixe de brincar um pouco com objetos da classe \texttt{GeradorDePrimos}
para enteder melhor como ela funciona! Agora um desafio para você: usando o
método \texttt{próximoPrimo}, escreva um novo método \texttt{void
imprimePrimos (int quantidadeDePrimos)} que imprime uma dada quantidade de
números primos a partir do \texttt{limiteInferior}. Experimente executar o
método passando 50 como parâmetro.


\section{Exercício:}

\begin{enumerate}
  
\item Escreva uma classe \texttt{TrianguloRetangulo} com um método denominado
  \texttt{defineLados(float x1, float x2, float x3} que recebe três valores e
  verifica se eles correspondem aos lados de um triângulo retângulo. Em caso
  afirmativo, o método retorna \texttt{true}, caso contrário ele retorna
  \texttt{false}.  Note que o programa deve verificar quais dos três valores
  corresponde à hipotenusa. Construa duas versões do método, uma contendo três
  \texttt{if}s e outra contendo apenas um \texttt{if}!
  
\item Escreva uma classe \texttt{Brincadeiras} que possua 3 atributos
  inteiros. Escreva um método para carregar valores nestes atributos e, em
  seguida, escreva os seguintes métodos:

\begin{enumerate}
\item \texttt{troca2Primeiros()} que troca os valores dos dois primeiros
  atributos. Por exemplo, se antes da chamada do método o valor dos atributos
  é <1, 2, 3>, depois da chamada, eles deverão valer <2, 1, 3>.
\item \texttt{imprime()} que imprime o valor dos 3 atributos.
\item \texttt{imprimeEmOrdemCrescente()} que imprime o valor dos 3 atributos em ordem crescente.
\end{enumerate}

\item A linguagem Java oferece operadores que, se usados corretamente, ajudam
  na apresentação e digitação do código, tornando-o mais enxuto. Veremos neste
  exercício dois deles: os operadores de incremento e de decremento.
  Verifique o funcionamento desses operadores usando os métodos da classe
  abaixo.

\begin{lstlisting}
class Experiência
{
  void verIncremento (int n)
  {
    int x = n;
    System.out.println ("Número inicial x -> " + x);
    System.out.println ("x++              -> " + x++);
    System.out.println ("Novo valor de x  -> " + x);

    x = n;
    System.out.println ("Número inicial x -> " + x);
    System.out.println ("++x              -> " + ++x);
    System.out.println ("Novo valor de x  -> " + x);
  }
  void verDecremento (int n)
  {
    int x = n;
    System.out.println ("Número inicial x -> " + x);
    System.out.println ("x--              -> " + x--);
    System.out.println ("Novo valor de x  -> " + x);

    x = n;
    System.out.println ("Número inicial x -> " + x);
    System.out.println ("--x              -> " + --x);
    System.out.println ("Novo valor de x  -> " + x);
  }
}
\end{lstlisting}

Entenda bem o código e observe os resultados. Em seguida, tire suas conclusões e compare-as com as conclusões de seus colegas.

\end{enumerate}

%\end{document}
