SkillsTecnológicas
Menu
Conteúdo da trilha

Contadores e acumuladores

Diferencie contadores e acumuladores, acompanhe resultados parciais e inicialize corretamente soma, produto, média, mínimo e máximo.

Conteúdo 31 de 39

Fichas desenhadas a lápis passam por um filtro e alimentam em paralelo um contador de ocorrências e um recipiente que acumula seus valores

Contador responde “quantos”; acumulador constrói um resultado

Contadores e acumuladores são variáveis que preservam estado entre iterações, mas cumprem papéis diferentes:

  • um contador registra quantas vezes um evento ocorreu, normalmente adicionando uma unidade;
  • um acumulador combina cada novo valor com um resultado parcial, como em uma soma, produto ou concatenação.

Considere cinco valores hipotéticos de vendas:

120, -15, 80, 0, 200

Neste exemplo, somente valores maiores que zero representam vendas concluídas. Queremos descobrir:

  • quantas vendas foram concluídas;
  • qual foi o valor total dessas vendas;
  • qual foi o valor médio por venda concluída.

O contador responderá “quantas”; o acumulador responderá “quanto foi combinado”.

Três variáveis podem mudar sem exercer o mesmo papel

Um algoritmo que percorre os cinco valores com um laço for pode usar:

quantidadeValidas <- 0
total <- 0

PARA CADA valor EM vendas FAÇA
  SE valor > 0 ENTÃO
    quantidadeValidas <- quantidadeValidas + 1
    total <- total + valor
  FIM SE
FIM PARA

Se a linguagem exigir uma posição explícita, pode existir também posicao. Essa variável controla qual item será visitado. Ela não representa necessariamente um resultado do problema.

Compare os papéis:

VariávelPapelAtualização
posicaocontrole do percursoavança para cada item
quantidadeValidascontador do domíniosoma 1 somente para venda válida
totalacumuladorincorpora o valor da venda válida

Um contador de laço e um contador de negócio podem terminar com valores diferentes. O percurso visita cinco registros, mas apenas três satisfazem valor > 0.

Um item válido alimenta dois caminhos: o contador acrescenta uma unidade à quantidade e o acumulador acrescenta o valor do item ao total parcial
O contador ignora a magnitude do item; o acumulador usa o valor necessário para construir o resultado.

Ambos podem ser vistos como formas de acumulação de estado. A distinção é útil porque torna a intenção visível: contar ocorrências é um caso especializado, enquanto acumular pode empregar diferentes operações e tipos de valor.

Inicialize antes de começar a repetição

O estado deve existir antes da primeira passagem:

quantidadeValidas <- 0
total <- 0

Zero representa corretamente o resultado quando nenhuma venda foi processada. Também não altera a primeira adição:

0 + 120 = 120

Reinicializar dentro do corpo destrói o histórico:

PARA CADA valor EM vendas FAÇA
  total <- 0
  total <- total + valor
FIM PARA

Ao fim, total conserva apenas o efeito da última passagem. O valor parcial anterior é substituído por zero antes que o próximo item seja incorporado.

Esse erro pode passar despercebido quando o teste usa apenas um item. Casos com zero, um e vários itens revelam responsabilidades diferentes da inicialização.

Atualize somente quando o evento ou valor pertence ao resultado

A estrutura condicional determina quais itens participam:

SE valor > 0 ENTÃO
  quantidadeValidas <- quantidadeValidas + 1
  total <- total + valor
FIM SE

As duas atualizações precisam estar sob a mesma regra neste problema. Se o contador fosse incrementado para todos os registros e o total somente para os positivos, a média dividiria o valor correto por uma quantidade incompatível.

O rastreamento completo fica assim:

Itemvalor > 0quantidadeValidas depoistotal depois
120verdadeiro1120
-15falso1120
80verdadeiro2200
0falso2200
200verdadeiro3400
Cinco etapas mostram os valores 120, menos 15, 80, zero e 200; apenas os positivos elevam o contador até 3 e o total até 400
Quando um item não atende à condição, o estado anterior é preservado para a passagem seguinte.

“Não atualizar” também é uma decisão de estado. Depois de -15, quantidade e total continuam representando apenas as vendas válidas já vistas.

Use invariantes para explicar o resultado parcial

Uma invariante do laço é uma afirmação que permanece verdadeira em pontos equivalentes da repetição. Depois de processar qualquer quantidade de itens do exemplo:

  • quantidadeValidas é o número de valores positivos já processados;
  • total é a soma dos valores positivos já processados.

Antes do primeiro item, ambas são verdadeiras: nenhum valor positivo foi visto, então quantidade e soma são zero.

Quando chega um valor inválido, nenhuma variável muda e as afirmações continuam verdadeiras. Quando chega um valor válido, somar uma unidade à quantidade e o próprio valor ao total preserva as duas afirmações.

Ao terminar o percurso, “itens já processados” significa a sequência inteira. As invariantes se transformam nas propriedades desejadas do resultado final.

Essa verificação é mais forte do que conferir apenas 3 e 400: ela explica por que o algoritmo funciona para outras sequências.

Calcule a média somente quando existe denominador

A média depende dos dois resultados:

SE quantidadeValidas > 0 ENTÃO
  media <- total / quantidadeValidas
  EXIBIR media
SENÃO
  EXIBIR "Nenhuma venda válida"
FIM SE

Para o exemplo:

media = 400 / 3
media ≈ 133,33

Não divida pelo número total de registros, pois os valores inválidos não entraram na soma. Também não divida antes de confirmar que quantidadeValidas é maior que zero.

Calcular a média dentro de cada passagem produziria médias parciais. Isso pode ser desejado para acompanhar evolução, mas é trabalho desnecessário quando apenas o resultado final importa.

Em um sistema real, tipo numérico e arredondamento de valores monetários precisam seguir a regra do domínio. Aqui usamos inteiros para concentrar a explicação no padrão de estado.

O valor inicial depende da operação

Zero funciona para soma e contagem, mas não para todo acumulador. O valor inicial deve representar o resultado antes de receber itens e não distorcer a primeira combinação.

ObjetivoInicialização comumAtualização
contar ocorrências0quantidade + 1
somar valores0total + valor
multiplicar valores1produto * valor
concatenar textotexto vaziotexto + parte
verificar se algum atendefalsoalgum OU condicao
verificar se todos atendemverdadeirotodos E condicao

Esses valores são neutros para as respectivas operações: combinar um valor com eles mantém o valor.

0 + x = x
1 * x = x
falso OU x = x
verdadeiro E x = x
Cartões relacionam soma e contagem a zero, produto a um, concatenação a texto vazio, algum a falso, todos a verdadeiro e mínimo ou máximo ao primeiro valor válido ou ausência
A inicialização faz parte do significado do algoritmo e precisa tratar conscientemente o caso sem itens.

Usar zero para um produto faria qualquer resultado permanecer zero. Iniciar “todos atendem” com falso impediria que o acumulador se tornasse verdadeiro usando E.

Mínimo e máximo exigem presença explícita

Para encontrar o maior valor, iniciar com zero falha quando todos os valores válidos são negativos. O algoritmo devolveria zero mesmo que ele nunca aparecesse na entrada.

Uma estratégia segura é representar a ausência até encontrar o primeiro item válido:

maior <- AUSENTE

PARA CADA valor EM valores FAÇA
  SE valor for válido ENTÃO
    SE maior está AUSENTE OU valor > maior ENTÃO
      maior <- valor
    FIM SE
  FIM SE
FIM PARA

Depois do laço:

  • se maior continua ausente, não havia valor válido;
  • caso contrário, ele contém o maior valor encontrado.

Outra possibilidade é inicializar com o primeiro valor válido e percorrer os restantes. As duas estratégias obrigam o algoritmo a tratar a sequência vazia, em vez de inventar um número que pareça pequeno ou grande o bastante.

Constantes como infinito positivo ou negativo podem ser adequadas em contextos numéricos específicos, mas não generalizam para textos, datas ou tipos próprios. Presença explícita comunica melhor a ausência de resultado.

Implemente o exemplo em JavaScript e Python

JavaScript

const vendas = [120, -15, 80, 0, 200];
let quantidadeValidas = 0;
let total = 0;

for (const valor of vendas) {
  if (valor > 0) {
    quantidadeValidas += 1;
    total += valor;
  }
}

const media = quantidadeValidas > 0
  ? total / quantidadeValidas
  : null;

console.log({ quantidadeValidas, total, media });

Resultado aproximado:

{ quantidadeValidas: 3, total: 400, media: 133.333... }

Python

vendas = [120, -15, 80, 0, 200]
quantidade_validas = 0
total = 0

for valor in vendas:
    if valor > 0:
        quantidade_validas += 1
        total += valor

media = total / quantidade_validas if quantidade_validas > 0 else None

print(quantidade_validas, total, media)

O padrão independe da sintaxe: inicializar antes, percorrer, selecionar, atualizar e interpretar o resultado depois.

APIs como reduce também descrevem uma redução em que um resultado parcial recebe o próximo elemento. Entender o laço explícito primeiro ajuda a escolher um valor inicial correto e a depurar versões mais abstratas.

Diagnostique pelos resultados que não podem acontecer

O total contém apenas o último valor

Provavelmente o acumulador foi reinicializado dentro do laço ou recebeu total <- valor em vez de total <- total + valor.

A quantidade é maior que o número de válidos

O contador pode estar fora da condição ou ser incrementado mais de uma vez na mesma passagem.

A média está menor do que deveria

Confira se soma e quantidade usam exatamente o mesmo critério de inclusão.

O produto permanece zero

A inicialização provavelmente usou o neutro da soma em uma multiplicação.

O maior valor é zero sem existir zero na entrada

Um sentinela arbitrário entrou no resultado. Use ausência explícita ou o primeiro item válido.

O caso vazio causa divisão ou resultado inventado

Defina antes o significado da ausência: zero, texto vazio, falso, verdadeiro, valor ausente ou erro podem ser respostas diferentes, conforme a operação e o domínio.

Teste o estado, não apenas a última saída

Inclua pelo menos:

  • sequência vazia;
  • um item válido;
  • um item inválido;
  • mistura de válidos e inválidos;
  • todos inválidos;
  • valores negativos quando forem permitidos;
  • primeiro e último itens válidos;
  • repetição do mesmo valor.

Faça um teste de mesa e confira as invariantes depois de cada passagem. Para a média, verifique separadamente soma, quantidade e decisão sobre divisão.

Pratique com tempos de atendimento

Considere:

12, 0, 8, 15, -1, 10

Valores positivos representam atendimentos concluídos. Construa um algoritmo que produza:

  1. quantidade de atendimentos válidos;
  2. soma dos tempos;
  3. média dos tempos válidos;
  4. maior tempo válido, ou ausência quando não houver nenhum.

Registre o estado após cada item e escreva três invariantes: uma para quantidade, outra para soma e outra para maior valor. Teste também uma sequência vazia, somente valores inválidos e [-5, -2] sob duas regras diferentes: negativos inválidos e negativos permitidos.

O que você deve guardar

Um contador registra quantas ocorrências atendem a uma regra. Um acumulador combina valores e conserva um resultado parcial. Ambos precisam ser inicializados antes da repetição e atualizados somente quando o item pertence ao resultado.

Escolha o valor inicial pela operação e pelo significado do caso vazio; não confunda posição do percurso com quantidade do domínio; proteja médias contra divisão por zero; e trate mínimo e máximo sem sentinelas inventadas. Em seguida, aprenda a criar condições de parada e diagnosticar laços infinitos acompanhando como o estado se aproxima da saída.

Referências