SkillsTecnológicas
Menu
Conteúdo da trilha

Conteúdo 20 de 20

Precedência de operadores e construção de expressões

Diferencie precedência, associatividade e ordem de avaliação, usando parênteses e resultados intermediários para construir expressões sem ambiguidades.

Publicado em 10 de setembro de 202618 min de leituraSkills Tecnológicas

Peças geométricas desenhadas a lápis atravessam molduras aninhadas até formar um resultado organizado e verificado

O que é precedência de operadores

Precedência de operadores é a regra que define como uma expressão com diferentes operadores será agrupada. Operadores de maior precedência formam seus grupos antes dos de menor precedência.

Na aritmética habitual:

2 + 3 * 4

A multiplicação agrupa primeiro. A expressão equivale a 2 + (3 * 4) e resulta em 14, não em (2 + 3) * 4, que resultaria em 20.

Isso não significa simplesmente “executar da esquerda para a direita”. A posição visual é apenas uma parte da leitura; os operadores e os parênteses determinam a estrutura.

Uma expressão possui camadas

Quando cálculos, comparações e operadores lógicos aparecem juntos, o resultado de uma camada alimenta a seguinte:

2 + 3 * 4 >= 14 E verdadeiro

Adotando a ordem documentada para esse exemplo, a leitura é:

  1. multiplicar 3 * 4, obtendo 12;
  2. somar 2 + 12, obtendo 14;
  3. comparar 14 >= 14, obtendo verdadeiro;
  4. combinar verdadeiro E verdadeiro, obtendo verdadeiro.
Expressão dois mais três vezes quatro maior ou igual a quatorze E verdadeiro é resolvida em quatro camadas: multiplicação, adição, comparação e operação lógica
Cada operador recebe operandos simples ou resultados produzidos pela camada anterior.

Perceba também a mudança de tipo: as operações aritméticas produzem números; a comparação produz um valor lógico; o operador E combina valores lógicos. Revisar tipos de dados ajuda a detectar combinações que não fazem sentido.

Parênteses alteram ou explicitam o agrupamento

Parênteses permitem declarar qual trecho forma uma unidade:

2 + 3 * 4       resulta em 14
(2 + 3) * 4     resulta em 20

No primeiro caso, a precedência da multiplicação já cria 2 + (3 * 4). No segundo, os parênteses fazem a soma alimentar a multiplicação.

Parênteses também podem apenas documentar o agrupamento que a linguagem já faria:

subtotal >= 100 E clienteAtivo

(subtotal >= 100) E clienteAtivo

Se a linguagem dá à comparação precedência maior que o E, as duas expressões têm a mesma estrutura. A segunda, porém, mostra imediatamente que subtotal >= 100 é uma pergunta completa.

Use parênteses para tornar a intenção visível, mas não envolva cada valor sem necessidade. O objetivo é revelar blocos de significado.

Precedência não é associatividade

Precedência resolve a relação entre operadores de níveis diferentes. Associatividade resolve o agrupamento quando os operadores estão no mesmo nível.

Subtração e divisão são normalmente associativas à esquerda:

20 - 5 - 3

Isso é agrupado como (20 - 5) - 3, resultando em 12. Não equivale a 20 - (5 - 3), cujo resultado é 18.

Dois caminhos comparam vinte menos cinco menos três agrupado à esquerda, que resulta em doze, e vinte menos abre parênteses cinco menos três fecha parênteses, que resulta em dezoito
Mesmos valores e operadores podem produzir outro resultado quando os parênteses mudam o agrupamento.

Alguns operadores agrupam à direita. Atribuições encadeadas em linguagens como C# e JavaScript são um exemplo: a = b = 5 é interpretado como a = (b = 5). Exponenciação também possui regras particulares em várias linguagens.

Não tente memorizar todas as exceções como se fossem universais. Consulte a tabela da linguagem e use parênteses quando a associação fizer diferença.

Precedência não é ordem de avaliação dos operandos

Há uma terceira ideia: ordem de avaliação define quando cada operando é obtido. Considere:

obterA() + obterB() * obterC()

A precedência informa que o resultado de obterB() * obterC() será combinado pela soma. Ela não deve ser usada, sozinha, para concluir em que ordem as três funções serão chamadas. Essa regra pertence à especificação da linguagem.

C# e Python, por exemplo, documentam avaliação de operandos da esquerda para a direita em seus contextos, mas operadores condicionais podem interromper o processo. Em:

condicaoSegura E calcularSegundaCondicao()

o curto-circuito pode evitar a chamada da função quando condicaoSegura é falsa. Parênteses ao redor da chamada não obrigam sua execução:

condicaoSegura E (calcularSegundaCondicao())

Os parênteses agrupam; o operador lógico ainda pode decidir não avaliar o operando direito.

Uma hierarquia útil, mas não universal

Em muitas linguagens populares, expressões básicas seguem uma progressão semelhante:

Agrupamento aproximadoExemplos
parênteses e construções primárias(expressão), chamadas e acesso
operadores unáriosnegação e sinais
multiplicativos*, /, resto
aditivos+, -
relacionais e igualdade<, >=, ==, !=
operadores lógicosE antes de OU em várias linguagens
atribuição=, atribuições compostas

Essa tabela serve como mapa mental, não como contrato portátil. Python posiciona o not booleano abaixo das comparações e oferece comparações encadeadas. C# separa categorias relacionais e de igualdade. JavaScript possui operadores adicionais, como coalescência nula e encadeamento opcional, com restrições próprias.

Antes de implementar uma expressão importante:

  1. identifique a linguagem e a versão;
  2. consulte sua tabela oficial;
  3. confirme regras dos operadores usados;
  4. adicione parênteses que revelem a intenção;
  5. teste casos capazes de distinguir interpretações.

Construa expressões de dentro para fora

Imagine uma regra de benefício:

O cliente recebe o benefício se o pedido atingir R$ 100 e o cadastro estiver ativo, ou se houver um cupom válido.

Uma forma compacta seria:

preco * quantidade + frete >= 100 E clienteAtivo OU cupomValido

Ela mistura aritmética, comparação e lógica. Mesmo quando a precedência produz o agrupamento esperado, a regra de negócio ainda pode estar ambígua: o cupom permite que um cliente inativo receba o benefício?

Há pelo menos duas interpretações:

((preco * quantidade + frete) >= 100 E clienteAtivo) OU cupomValido

Aqui, um cupom válido é uma alternativa completa.

(((preco * quantidade + frete) >= 100) OU cupomValido) E clienteAtivo

Aqui, cadastro ativo é obrigatório em qualquer situação.

Precedência resolve a gramática da expressão; ela não decide o significado da política. Esse significado deve ser confirmado antes do código.

Prefira resultados intermediários em regras extensas

Uma expressão pode ser válida e ainda assim difícil de revisar. Dividi-la cria nomes para as perguntas:

subtotal <- preco * quantidade
valorPedido <- subtotal + frete
atingiuMinimo <- valorPedido >= 100

elegivelSemCupom <- atingiuMinimo E clienteAtivo
recebeBeneficio <- elegivelSemCupom OU cupomValido
Fluxo transforma preço vezes quantidade mais frete maior ou igual a cem E cliente ativo OU cupom válido em quatro resultados nomeados: subtotal, valor do pedido, atingiu mínimo e recebe benefício
Resultados intermediários tornam tipos, dependências e decisões observáveis.

A decomposição oferece três vantagens:

  • mostra a ordem conceitual sem exigir que o leitor memorize uma tabela;
  • permite inspecionar o resultado de cada etapa;
  • cria pontos naturais para testar cálculos e condições.

Isso não obriga todo programa a armazenar cada operação em uma variável. É uma ferramenta de clareza, especialmente útil enquanto a regra está sendo validada. Os mesmos princípios aparecem em como escrever pseudocódigo claro.

Como ler uma expressão existente

Use um procedimento sistemático:

1. Liste os operadores

Em preco * quantidade + frete >= 100 E clienteAtivo, há multiplicação, soma, comparação e conjunção.

2. Localize os parênteses

Cada par delimita uma subexpressão. Comece pelo grupo mais interno e avance para fora.

3. Consulte a precedência

Compare apenas os operadores que disputam o mesmo nível da expressão. Não é preciso decorar a tabela inteira.

4. Aplique a associatividade nos empates

Se dois operadores têm a mesma precedência, verifique como aquela linguagem os agrupa.

5. Anote tipo e resultado de cada grupo

preco * quantidade produz número; valor >= 100 produz lógico; condicao E clienteAtivo combina lógicos.

6. Reescreva com parênteses ou nomes

Se duas pessoas puderem interpretar a regra de formas diferentes, a expressão ainda não está clara o bastante.

Teste casos que separam interpretações

Um bom teste não confirma apenas o caminho mais comum. Ele escolhe valores que fariam agrupamentos diferentes produzir respostas distintas.

Para a regra de benefício, use:

Casoatingiu mínimocliente ativocupom válidoO que o caso revela
1verdadeiroverdadeirofalsoregra normal pelo valor
2falsoverdadeiroverdadeiroalternativa do cupom
3falsofalsoverdadeirose o cupom ignora cadastro
4verdadeirofalsofalsose cadastro é obrigatório

O caso 3 distingue as duas interpretações apresentadas. Faça um teste manual registrando cada resultado intermediário.

Erros comuns

Presumir que tudo acontece da esquerda para a direita

A leitura linear falha quando há operadores de precedências diferentes. Descubra primeiro a estrutura.

Confundir precedência com associatividade

Precedência compara níveis; associatividade desempata operadores do mesmo nível.

Acreditar que parênteses forçam uma chamada

Eles mudam agrupamento. Curto-circuito ainda pode impedir a avaliação de um operando.

Copiar a tabela de outra linguagem

Operadores parecidos não garantem a mesma hierarquia, a mesma associatividade nem os mesmos tipos aceitos.

Criar uma única expressão para toda a regra

Compactação excessiva esconde perguntas de negócio. Nomeie subexpressões quando isso melhorar revisão e teste.

Usar parênteses sem entender os tipos

Agrupar uma soma e depois compará-la é diferente de tentar somar um número a um resultado lógico. Acompanhe o tipo produzido em cada camada.

Checklist para expressões confiáveis

  • A intenção da regra está confirmada?
  • Sei quais operadores aparecem na expressão?
  • Consultei a precedência da linguagem usada?
  • Verifiquei a associatividade quando há empate?
  • Os parênteses revelam os grupos importantes?
  • Cada subexpressão recebe tipos compatíveis?
  • Separei precedência da ordem de avaliação?
  • Considerei curto-circuito e efeitos colaterais?
  • Uma decomposição em nomes deixaria a regra mais clara?
  • Testei valores que diferenciam agrupamentos possíveis?

Pratique com cálculo e elegibilidade

Uma entrega é gratuita quando o subtotal após desconto é pelo menos R$ 150 e o endereço está na área atendida. Um passe promocional também pode liberar o frete, mas apenas para endereços atendidos.

Use preco, quantidade, desconto, enderecoAtendido e passeValido para:

  1. calcular o subtotal bruto;
  2. aplicar o desconto;
  3. comparar o subtotal final com 150;
  4. agrupar a alternativa do passe;
  5. fazer enderecoAtendido valer para as duas alternativas;
  6. escrever primeiro a forma decomposta e depois uma forma compacta com parênteses.

Uma solução decomposta é:

subtotalBruto <- preco * quantidade
subtotalFinal <- subtotalBruto - desconto
atingiuMinimo <- subtotalFinal >= 150
possuiLiberacao <- atingiuMinimo OU passeValido
freteGratis <- possuiLiberacao E enderecoAtendido

A forma compacta correspondente é:

freteGratis <- (((preco * quantidade) - desconto) >= 150 OU passeValido) E enderecoAtendido

O que você deve guardar

Precedência determina quais operadores agrupam primeiro. Associatividade resolve operadores do mesmo nível. Ordem de avaliação determina quando os operandos são obtidos. São três conceitos relacionados, mas diferentes.

Use a documentação da linguagem como contrato, parênteses como comunicação e resultados intermediários como ferramenta de clareza. Assim, expressões deixam de ser sequências densas e passam a ser estruturas verificáveis. Continue pelo catálogo de Lógica de Programação.

Referências