O básico que todo mundo esquece
Para determinar se um número é par ou ímpar, você divide por dois e vê o resto. Se o resto for zero, é par. Se o resto for um, é ímpar. Isso parece óbvio até você precisar processar milhões de linhas de dados e descobrir que a forma como isso é implementado em alguma linguagem vai te causar dor de cabeça. números ímpares e pares não são apenas conceitos de escola primária. Eles aparecem em criptografia, em algoritmos de balanceamento, em indexação de arrays e em qualquer sistema que precise distribuir carga. A diferença entre um programador que sabe usar isso corretamente e um que não sabe é o tempo que você vai gastar debugando à meia-noite.
Como testar na prática
A forma mais direta em Python é usar o operador de módulo: n % 2 == 0. Em JavaScript, a mesma coisa. Em C ou Java, idem. O operador % retorna o resto da divisão inteira. Se você passar um número negativo, aqui entra o primeiro problema que muita gente ignora. No Python, -3 % 2 retorna 1, então um número negativo ímpar continua sendo detectado como ímpar. Mas em C, -3 % 2 retorna -1, e sua condição == 0 ainda funciona para pares, porém se você estiver usando != 0 para ímpares, precisa ter consciência de que o sinal importa. Já passei horas caçando um bug em um sistema legado onde um relatório de conciliação financeira simplesmente pulava transações negativas porque o validador de paridade não considerava o sinal do operador módulo em C++ antigo.
A solução que eu uso hoje é uma função utilitária que normaliza o número antes de testar: abs(n) % 2 == 0
Isso resolve 99% dos casos problemáticos. Os outros 1% envolvem números muito grandes onde o tipo de dado não comporta o valor absoluto devido ao overflow. Nesses cenários, testar o último dígito em base 10 é mais seguro, mas só funciona para inteiros. Ponto importante: floats não devem ser testados assim. 4.0 % 2 pode retornar algo como 1.9999999999999998 por causa de precisão de ponto flutuante, e seu teste de paridade falha silenciosamente.
Pegadinhas que ninguém conta
A primeira é sobre grandes volumes. Se você está iterando por milhões de registros e precisa separar pares de ímpares, usar % 2 dentro de um loop simples pode ser mais lento do que você imagina. A operação de módulo envolve uma divisão, e divisões são inerentemente mais custosas que operações bitwise. Para cada iteração, o processador faz uma divisão de 64 bits. Em um loop de 10 milhões, isso se acumula. A alternativa é usar bitwise: (n & 1) == 0. O bit menos significativo de um número par é sempre zero. O de um ímpar é sempre um. Essa verificação é basicamente gratuita para o CPU. Em benchmarks reais, essa troca reduziu o tempo de processamento de uma rotina de triagem de 47 segundos para 3 segundos. A diferença não é teórica. É real e mensurável.
👉 Clique no botão abaixo para saber mais sobre o assunto!
A segunda pegadinha é mais sutil e acontece em bancos de dados. O operador MOD() no MySQL e no PostgreSQL se comporta de maneira diferente para números negativos do que muitos desenvolvedores esperam. O PostgreSQL segue o padrão SQL, onde MOD(-3, 2) retorna -1. O MySQL retorna -1 também, mas do MySQL podiam dar resultados inconsistentes dependendo do collation e do tipo da coluna. Se você tem uma query que filtra por WHERE id MOD 2 = 1 e espera que todos os ímpares apareçam, números negativos vão sumir. A correção é usar ABS(id) MOD 2 = 1 ou, melhor ainda, reavaliar se você realmente precisa de paridade em negative IDs — o que normalmente indica um problema de modelagem.
Quando isso não funciona
Números fracionários não têm paridade. Não existe par ou ímpar para 2.5. Se o seu sistema recebe inputs de usuários e você está validando paridade sem garantir que o valor é um inteiro, você vai ter erros. Sempre converta para int com truncamento ou arredondamento explícito antes de testar. Decidir qual convenção de arredondamento usar — truncar para zero, floor, round — é tão importante quanto o teste em si. Outro cenário onde a paridade perde sentido é com tipos BigInt de bibliotecas personalizadas que usam representação internamente em base diferente de 10 ou 2. Em sistemas embarcados com aritmética de precisão variável, o operador módulo pode não estar disponível ou pode ter comportamento definido pelo fabricante. Nesses casos, testar o último nibble ou byte diretamente na representação binária é o único caminho confiável.
Um caso real
Trabalhei numa migração de um sistema de agendamento hospitalar onde os quartos eram numerados sequencialmente e a lógica de distribuição de pacientes alternava entre alas baseada na paridade do número do quarto. Quartos pares iam para a ala leste, ímpares para a ala oeste. O sistema original rodava em Delphi e usava Odd(Quarto). Quando migramos para uma API em Node.js, a equipe reimplementou a lógica usando quarto % 2 === 1 e simplesmente esqueceu que alguns registros no banco tinham números de quarto negativos — gerados por um bug antigo que nunca foi corrigido. Os pacientes desses quartos negativos não iam para lugar nenhum. A alocação falhava silenciosamente. Reescrevemos usando Math.abs(quarto) % 2 === 1 e adicionamos um filtro de dados órfãos que identificou 34 registros com quarto negativo. A correção levou duas horas. O bug original tinha nove meses.
O aprendizado prático foi: nunca confie na limpeza dos dados de entrada só porque o conceito matemático é simples. A paridade é simples. O contexto onde ela é aplicada raramente é.
Resumo prático
Use abs(n) % 2 == 0 como regra padrão. Para loops em larga escala, substitua por (abs(n) & 1) == 0. Nunca aplique test de paridade diretamente em floats. Em SQL, verifique como o MOD se comporta com negativos no seu SGBD específico. E antes de confiar em qualquer implementação, pergunte-se se os dados que estão entrando no sistema são realmente inteiros e não negativos. O resto é matemática básica. O difícil é garantir que o resto do sistema também entenda isso.