A função
apresentada em quatro implementações diferentes em um dos slides na Aula
recebe três números e retornar o maior dentre eles. A função
() apresentada a seguir também deveria retornar o maior dentre três números, mas não o faz para todos os valores de entrada.
(a) Apresente uma lista com valores de entrada e os respectivos valores de saída esperados, a qual poderia ser utilizada como teste para verificar se a implementação da função max3X () está correta ou não.
(b) Qual(is) “caso(s)” (valores de entrada) faz(em) com que a função max3X() não retorne o maior dos três números utilizados como valores de entrada?
float max3X( float v1, float v2 , float v3 ) {
if ( ( v1 > v2 ) && ( v1 > v3 ) )
return v1;
if ( ( v2 > v1 ) && ( v2 > v3 ) )
return v2;
return v3;
}'
(a) Apresente uma lista com valores de entrada e os respectivos valores de saída esperados, a qual poderia ser utilizada como teste para verificar se a implementação da função max3X () está correta ou não.
(b) Qual(is) “caso(s)” (valores de entrada) faz(em) com que a função max3X() não retorne o maior dos três números utilizados como valores de entrada?
float max3X( float v1, float v2 , float v3 ) {
if ( ( v1 > v2 ) && ( v1 > v3 ) )
return v1;
if ( ( v2 > v1 ) && ( v2 > v3 ) )
return v2;
return v3;
}'Passo 1
O enunciado dá a função abaixo (em C) que deveria retornar o maior entre três números, mas pode falhar:
O que o enunciado pede:
(a) Apresentar uma lista de valores de entrada (tripletas) com os respectivos valores de saída esperados — ou seja, um conjunto de testes que permita verificar se a implementação está correta.
(b) Indicar quais caso(s) (quais valores de entrada) fazem com que a função não retorne o maior dos três números.
(a) Apresentar uma lista de valores de entrada (tripletas) com os respectivos valores de saída esperados — ou seja, um conjunto de testes que permita verificar se a implementação está correta.
(b) Indicar quais caso(s) (quais valores de entrada) fazem com que a função
Passo 2
Vou explicar claramente como a função funciona e onde pode haver problema — passo a passo, sem pular etapas.
A função compara os números com duas condições sequenciais:
A função compara os números com duas condições sequenciais:
- Primeiro faz a verificação
e . Se ambas forem verdadeiras, retorna . Isso cobre o caso em que é estritamente maior que os outros dois. - Se a primeira condição falhar, faz a verificação
e . Se ambas verdadeiras, retorna . Isso cobre o caso em que é estritamente maior que os outros dois. - Se nenhuma das duas condições for satisfeita, a função retorna
.
Observe a palavra chave: “estritamente maior” — o código usa o operador
, não
. Isso significa que sempre que houver igualdade entre dois valores, as comparações que exigem estrita superioridade podem falhar mesmo que esses valores sejam de fato os máximos (por estarem empatados). É justamente aí que mora o bug: empates entre os dois primeiros argumentos podem fazer a função pular as duas condições e devolver
, que pode ser menor.
Passo 3
Agora monto uma lista de testes (tripletas) com o resultado esperado em cada caso. Esses testes foram escolhidos para cobrir: todas as ordens possíveis sem empates, empates entre diferentes pares, todos iguais e casos com negativos/decimais — assim você detecta o bug na implementação.
Testes (entrada
saída esperada):
Por quê esses testes?
- Os três primeiros cobrem permutações sem empates (todas as ordens distintas). A implementação correta deve retornar sempre o maior.
-
é o teste que expõe o bug potencial: os dois primeiros são iguais e maiores que o terceiro — aqui esperamos . -
e verificam empates envolvendo o terceiro elemento emparelhado com outro — são importantes porque a função pode retornar e aí esses casos ajudam a confirmar comportamento. -
verifica caso todos iguais. - Casos com negativos e decimais verificam que a função lida com sinais e pontos flutuantes corretamente.
Execute esses testes na implementação; se algum deles produzir saída diferente do esperado, a função está errada.
Passo 4
Mostro exatamente por que e quando a função falha — com uma demonstração passo a passo numérica e lógica.
Considere o caso
. Esperamos
. Agora avalie a função linha a linha:
- Primeiro
é , que é falso (porque não é estritamente maior, é igual). Logo a conjunção é falsa, então não retorna . - Segundo
é , também falso; portanto a segunda conjunção é falsa, então não retorna . - Como nenhum dos dois ifs retornou, a função executa o
e devolve .
Resultado: a função devolve
quando o correto seria
. Ou seja, ela falha nesse caso.
Em linguagem geral: qualquer situação em que os dois primeiros argumentos empatam no maior valor e esse valor é maior que o terceiro — isto é, quando
faz com que ambas as condições
e
sejam falsas, então a função retorna
(errado).
Verifique outros empates:
- Se
: a função retorna . Mas como e esse é o máximo, o valor retornado é correto. - Se
: a função retorna (que é igual ao máximo) — correto. - Se
: a função retorna — correto (todos iguais).
Portanto o único padrão de entrada que causa erro é quando os dois primeiros argumentos são iguais e esse valor é estritamente maior que o terceiro.
Passo 5
Resumo didático e dica para consertar (para você entender como resolver na prova):
- A raiz do erro é o uso de comparações estritas
em vez de permitir igualdade para cobrir empates. Uma correção simples (que resolve o caso problemático) é usar em pelo menos uma das verificações iniciais, por exemplo testar se é maior ou igual aos outros dois antes de retornar . Outra alternativa bem comum e robusta é inicializar um valor e então fazer: - se
então , - se
então , - retornar
.
Esse último método evita problemas de empates e é o padrão que eu usaria na prova porque é simples e fácil de justificar passo a passo.
- se
Resposta
(a) Testes e saídas esperadas:
(b) A função falha quando os dois primeiros argumentos empatam e são maiores que o terceiro, isto é, para entradas que satisfazem
(por exemplo
, que faz a função retornar
em vez de
).