Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

Acumulador e média: somar valores dentro do laço

A diferença entre contador e acumulador, por onde a média sai errada e o caso da lista vazia que divide por zero, tudo executado no Node.

Rodolfo Mori4 min de leitura

Acumulador guarda um resultado parcial que cresce a cada volta; contador registra quantas ocorrências ou voltas foram consideradas. Para calcular média, você soma, conta e divide uma única vez depois do laço.

O boletim desta lição tem cinco notas: 7, 8, 9, 6 e 10. A soma é 40 e a média é 8. O resultado conhecido permite comparar três implementações e localizar a volta em que duas delas se afastam da correta.

Contador conta ocorrências; acumulador soma valores

As duas variáveis mudam juntas, mas carregam unidades diferentes:

js
const notas = [7, 8, 9, 6, 10];
let contador = 0;
let soma = 0;

for (const nota of notas) {
  contador += 1;
  soma += nota;
}

console.log({ contador, soma });
{ contador: 5, soma: 40 }

Pense em duas colunas de uma planilha: uma marca quantas linhas válidas entraram; outra guarda o total dos valores. O limite da analogia é que um acumulador pode guardar texto, produto, maior valor ou objeto, não apenas soma.

Misturar as unidades produz regras sem sentido, como dividir nota acumulada pelo próprio total. Nomear quantidadeDeNotas e somaDasNotas deixa o contrato visível sem comentário.

Inicialize fora do laço

Se soma = 0 ficar dentro do corpo, cada volta apaga o trabalho anterior:

js
const notas = [7, 8, 9];
let soma;

for (const nota of notas) {
  soma = 0;
  soma += nota;
  console.log(soma);
}
7 8 9

O último valor é apenas a última nota. A pergunta de revisão é: qual estado precisa sobreviver de uma volta para a seguinte? Esse estado nasce antes do laço e recebe atualização dentro dele.

Soma começa em zero; produto começa em um

O valor inicial deve ser neutro para a operação. Somar zero não altera; multiplicar por um não altera:

js
const valores = [2, 3, 4];
let soma = 0;
let produto = 1;

for (const valor of valores) {
  soma += valor;
  produto *= valor;
}

console.log({ soma, produto });
{ soma: 9, produto: 24 }

Produto iniciado em zero ficaria zero na primeira multiplicação e nunca se recuperaria. Para maior ou menor, zero não é neutro quando todos os valores podem ser negativos; use o primeiro item ou infinitos adequados.

A média acontece em três movimentos

Faça o processamento em ordem: acumular, contar, dividir. A divisão ocorre quando o total está completo:

js
const notas = [7, 8, 9, 6, 10];
let soma = 0;

for (const nota of notas) soma += nota;

const quantidade = notas.length;
const media = soma / quantidade;
console.log({ soma, quantidade, media });
{ soma: 40, quantidade: 5, media: 8 }

Dividir depois do laço preserva uma frase matemática simples: média é soma final sobre quantidade final. A lição de laço e contador ajuda a prever quantas voltas alimentam esses dois valores.

Dividir dentro do laço cria um número quase plausível

Uma implementação defeituosa divide o acumulador por cinco a cada volta e reutiliza o resultado parcial:

js
const notas = [7, 8, 9, 6, 10];
let valor = 0;

for (const nota of notas) {
  valor = (valor + nota) / notas.length;
}

console.log(valor);
2.3270399999999998

O resultado não é média parcial. Cada nota antiga é dividida repetidas vezes, enquanto a última é dividida apenas uma. A ordem das notas passa a mudar a saída, embora a média de um conjunto não dependa da ordem.

Prove trocando a ordem:

js
function mediaErrada(notas) {
  let valor = 0;
  for (const nota of notas) valor = (valor + nota) / notas.length;
  return valor;
}

console.log(mediaErrada([7, 8, 9, 6, 10]));
console.log(mediaErrada([10, 6, 9, 8, 7]));
2.3270399999999998 1.8048000000000002

Esse teste metamórfico é poderoso: uma transformação que deveria preservar o resultado — reordenar notas — expõe o defeito sem exigir conhecer toda a implementação.

Acumulador iniciado em um desloca todas as médias

O segundo erro preserva a ordem, mas acrescenta um ponto fantasma à soma:

js
const notas = [7, 8, 9, 6, 10];
let soma = 1;

for (const nota of notas) soma += nota;
console.log(soma / notas.length);
8.2

A diferença é 1 / 5, por isso a saída sobe 0,2. O teste de mesa localiza o desvio antes da primeira volta: quando nenhuma nota foi somada, o total já vale um.

Lista vazia divide zero por zero

JavaScript devolve NaN e não lança exceção:

js
const notas = [];
const soma = notas.reduce((total, nota) => total + nota, 0);
const media = soma / notas.length;

console.log(media);
console.log(Number.isNaN(media));
NaN true

Não conserte com media || 0: isso mistura resultado inválido e uma média legítima zero. Trate a pré-condição com uma decisão explícita:

js
function calcularMedia(notas) {
  if (notas.length === 0) throw new RangeError('A lista de notas está vazia');
  return notas.reduce((soma, nota) => soma + nota, 0) / notas.length;
}

try {
  calcularMedia([]);
} catch (erro) {
  console.log(`${erro.name}: ${erro.message}`);
}
RangeError: A lista de notas está vazia

A mensagem nomeia a entrada que viola o contrato. Outro produto poderia retornar null; documente a escolha para quem chama a função.

Maior e menor também acumulam estado

Nem todo acumulador soma. Para encontrar extremos, guarde o melhor valor visto até agora. Começar pelo primeiro item evita o erro com listas negativas:

js
const temperaturas = [-8, -3, -12, -5];
let maior = temperaturas[0];
let menor = temperaturas[0];

for (const temperatura of temperaturas.slice(1)) {
  if (temperatura > maior) maior = temperatura;
  if (temperatura < menor) menor = temperatura;
}

console.log({ maior, menor });
{ maior: -3, menor: -12 }

Se maior começasse em zero, a resposta seria zero, que nem pertence à lista. O estado inicial precisa representar um resultado possível ou um neutro válido.

Antes da missão, compare média simples e ponderada pelo significado da contagem. Na simples, cada nota contribui uma ocorrência e o divisor é quantidade. Na ponderada, cada nota contribui peso ocorrências equivalentes e o divisor é soma dos pesos. Usar quantidade na segunda produz valor errado mesmo que o acumulador esteja correto.

Registre unidades no rastreio: somaNotaPeso carrega pontos vezes peso, enquanto somaPesos carrega peso. A divisão devolve pontos. Essa análise dimensional encontra erros que uma entrada isolada pode esconder.

Se as notas chegam aos poucos, você pode guardar soma e quantidade, mas precisa atualizá-las numa operação única para que não divirjam. Em dados persistidos, considere recalcular a partir da fonte quando consistência importa mais que custo. Acumulador duplicado é estado que precisa de contrato.

Teste também valores decimais e extremos aceitos. Formatação deve ocorrer depois do cálculo; arredondar cada volta altera a soma acumulada. Para dinheiro, trabalhe em unidade inteira menor. Para notas, defina quantas casas pertencem à regra e quantas pertencem apenas à exibição.

Sua missão é calcular média ponderada de três avaliações com pesos 2, 3 e 5. Use dois acumuladores: soma de nota * peso e soma dos pesos. O critério é obter 8,1 para notas 7, 8 e 9, e rejeitar lista vazia. Depois avance para vetor e matriz, acompanhe o percurso no guia de lógica e pratique na trilha.

  • acumulador
  • media
  • contador
  • divisao por zero
  • somatorio

Perguntas frequentes

Contador e acumulador podem ser a mesma variável?
Só quando cada ocorrência adiciona exatamente um e você não precisa dos dois resultados. Para média, mantenha quantidade e soma separadas porque representam unidades diferentes.
O que uma função de média deve devolver para lista vazia?
Não há resposta universal. Ela pode lançar erro, devolver null ou usar uma regra do produto. O importante é declarar o contrato e não deixar NaN escapar silenciosamente.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Node v26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. ECMAScript — For Statement — tc39.es
  2. ECMAScript — Number.isNaN — tc39.es

Continue por aqui