O que é conjunto dos números inteiros
A gente usa isso todo dia sem perceber. Quando você diz que perdeu 15 reais, que está 3 graus abaixo de zero, ou que o depósito bancário rendeu -0,7%, tá operando com conjunto dos números inteiros. A notação formal é Z, vem do alemão Zahlen, e abrange todos os naturais (0, 1, 2, 3...) mais os opostos negativos (-1, -2, -3...). É isso. Não tem mistério. O que muita gente não entende de primeira é a diferença entre Z e N (naturais). Natural só vai pro positivo, incluindo o zero na maioria das convenções brasileiras. Inteiro cruza a linha e entra no negativo. Se você faz análise de dados ou trabalha com planilhas financeiras, essa distinção costuma dar dor de cabeça quando o sistema aceita valores negativos em campos que deveriam ser só naturais. Já vi coluna de "idade" ou "quantidade de peças" receber -5 num formulário porque o backend não validava o tipo corretamente.
Propriedades do conjunto dos números inteiros
Z é fechado para adição, subtração e multiplicação. Isso significa que somar, subtrair ou multiplicar dois inteiros sempre gera outro inteiro. Divisão é a exceção: 5 dividido por 2 dá 2,5, que sai fora do conjunto. Aí você precisa dos racionais (Q). Outra coisa que passa despercebida: Z é um domínio de integridade. Não existem divisores de zero. Se a·b = 0, então obrigatoriamente a = 0 ou b = 0. Isso parece óbvio demais, mas é o que permite resolver equações do tipo (x-3)(x+7) = 0 e dizer que x = 3 ou x = -7 sem ambiguidade. Em anéis mais gerais, isso não vale.
Eu trabalhei num projeto de cálculo de estacionamento automatizado onde precisávamos contabilizar horas extras e horas devidas. O sistema usava inteiros para representar minutos, com positivos pra crédito e negativos pra débito. O bug clássico: alguém inseriu -1441 minutos (um minuto além de 24h negativo) e a lógica de arredondamento pra diária inteira quebrava porque a função Math.floor() se comporta diferente de Math.trunc() pra números negativos. floor(-1441/60) dá -24, mas trunc(-1441/60) dá -24 também... espera, nesse caso não tem diferença. O problema real era com -1439: floor dá -24, trunc dá -23. A correção foi usar Math.trunc() e validar o range manualmente entre -1440 e 1440 minutos por diária.
Operações fundamentais com inteiros
Regra de sinal na multiplicação e divisão todo mundo decorou na escola, mas na prática as pessoas erram quando o número de negativos é ímpar. Produto de três números negativos dá negativo. Quatro, positivo. Cinco, negativo de novo. O padrão é alternado e fácil de perder de vista quando os termos estão espalhados numa expressão longa. Na adição, a regra é simples: mesmo sinal, soma os módulos e mantém o sinal. Sinal diferente, subtrai os módulos e fica com o sinal do maior em valor absoluto. Parece bobeira escrever isso, mas em programação linguagem como JavaScript converte strings pra números de forma inconsistente. "-5" + 3 vira "-53", não -2. O operador + faz concatenação quando um dos operandos é string. Tem que forçar a conversão explícita com Number() ou parseInt() antes de operar.
O máximo divisório comum (MDC) e o mínimo múltiplo comum (MMC) são ferramentas úteis que quase ninguém usa depois do ensino médio. O algoritmo de Euclides calcula MDC de dois inteiros em tempo logarítmico. Dois números quaisquer, digamos 1071 e 462, o MDC se resolve em três passos: 1071 = 2·462 + 147, depois 462 = 3·147 + 21, depois 147 = 7·21 + 0. MDC é 21. Rápido. Prático pra simplificar frações e pra checksum em protocolos de comunicação onde você precisa de resíduos congruentes.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Congruência e aritmética modular
Aqui é onde inteiro vira algo mais pesado. Dois números são congruentes módulo n quando a diferença entre eles é divisível por n. Escreve-se a b (mod n). Isso não é curiosidade matemática — é a base de criptografia RSA, de códigos de verificação de CPF e CNPJ no Brasil, e de sistemas de hash. O CPF usa módulo 11. O dígito verificador é calculado como o resto da divisão da soma ponderada dos onze primeiros dígitos por 11. Se o resto for maior que 9, o dígito é 0. Simples, mas um erro de implementação pode aceitar CPF inválido como válido, e isso já aconteceu em sistemas de alta frequência porque o desenvolvedor esqueceu de tratar o caso em que o resto é 10. Uma propriedade importante que as pessoas ignoram: a congruência é uma relação de equivalência. Isso significa que ela partitions Z em classes de equivalência. Para módulo 3, temos exatamente três classes: os que deixam resto 0, os que deixam resto 1 e os que deixam resto 2. Qualquer inteiro cai em exatamente uma dessas classes. Não existe meio-termo. Isso é útil pra validar dados e pra detectar padrões cíclicos em sequências.
No meu caso, estava construindo um gerador de senhas temporárias baseado em sequência linear congruencial. A fórmula é Xn+1 = (a·Xn + c) mod m, onde m é o módulo. Escolhi m = 2^31 - 1 (um primo de Mersenne, que é um inteiro). O problema é que o período máximo dessa sequência é m - 1, e pra atingir esse período preciso que a - 1 seja divisível por todos os fatores primos de m, e que a - 1 seja divisível por 4 se m for par. Como m é ímpar, só precisa da primeira condição. Escolhi a = 16807 e c = 0, que é o parâmetro do MINSTD, um gerador validado. O resultado: sequência de período completo, boa distribuição uniforme, e o melhor — implementação em menos de cinco linhas sem dependências externas. O único senão é que sequences lineares congruenciais não são criptograficamente seguras. Qualquer um que observe 3 ou 4 valores consecutivos consegue reconstruir o estado interno. Pra senha temporária com validade de 5 minutos e uso interno, era suficiente. Pra algo exposto publicamente, não.
Por que o conjunto dos inteiros importa na prática
Em ciência da computação, inteiros têm representação finita. Um int32 vai de -2.147.483.648 a 2.147.483.647. Um int64 sobe pra cerca de ±9 quintilhões. Quando você ultrapassa esse limite, o valor transborda (overflow) e volta pro extremo oposto em aritmética de duas complementos. Isso causa bugs silenciosos que parecem magia negra: um contador de eventos que de repente vira negativo, um timestamp que retrocede, um preço que explode pra valores absurdos. O ataque Heartbleed da OpenSSL explorava justamente um overflow de tamanho de buffer que não era validado. Em Python, inteiros têm precisão arbitrária. Não existe overflow porque a linguagem aloca memória extra automaticamente. Isso é vantagem e desvantagem: você não se preocupa com limites, mas paga custo de performance em operações com números muito grandes. Em Go, inteiros são fixos e o compilador não te protege de overflow em runtime. Em Rust, overflow em debug causa panic; em release, faz wrap-around silencioso. Você escolhe o comportamento com saturating_add() ou wrapping_add(). Conheço devs que migraram de Python pra Rust e levaram meses praar a ideia de que o compilador vai te obrigar a pensar em tudo que em Python era implícito.
Outro ponto prático: zero é inteiro, mas nem todo mundo trata como tal. Em algumas implementações de banco de dados, campos do tipo SERIAL ou AUTO_INCREMENT começam em 1, não em 0. Se seu sistema precisa de identificadores que incluam zero, você tem que ajustar o seed inicial. Já vi sistema de filas onde o item 0 era interpretado como "inexistente" porque o framework usava null pra ausência, e 0 como valor válido colidia com essa convenção. A correção foi usar nil pointer em Go em vez de int zerado.
Extensões e limites do conceito
Se Z não fecha pra divisão, os racionais (Q) surgem como extensão natural. Frações a/b onde a e b são inteiros e b 0. Q fecha pra todas as quatro operações básicas. Depois vêm os reais (R), que incluem irracionais como 2 e . E os complexos (C), com parte imaginary i = -1. Cada passo resolve uma limitação do anterior, mas ganha complexidade nova. Uma coisa que pouca gente sabe: Z é um anel euclidiano. Isso quer dizer que existe uma função norma (no caso, o valor absoluto) que permite realizar divisão com resto de forma bem comportada. Isso garante que todo ideal em Z é principal, e que todo inteiro positivo se fatora de maneira única em primos. Teorema fundamental da aritmética. Sem essa propriedade, criptografia moderna como RSA não funcionaria, porque a segurança depende exatamente da dificuldade de fatorar números grandes em seus fatores primos — e isso só faz sentido porque a fatoração é única.
Inteiros gaussianos, Z[i], estendem Z adicionando o número imaginário i. Nesse anel, a fatoração única ainda vale, mas os primos se comportam de jeito diferente. Um primo como 3 em Z pode se fatorar em Z[i] se for da forma 4k+3... espera, na verdade primos da forma 4k+3 permanecem primos em Z[i], enquanto primos da forma 4k+1 se fatoram em dois conjugados. O número 2 é caso especial: 2 = (1+i)(1-i), e 1-i = -i(1+i), então na verdade 2 = -i(1+i)^2. O fator primo é 1+i, com norma 2. Isso é útil em codificação e em algoritmos de graduação rápida. Pra quem quer aplicar inteiros no dia a dia: se você programa, trate sempre a faixa de valores que seu tipo suporta. Se trabalha com finanças, use inteiros pra centavos em vez de floats pra reais — evita erro de precisão. Se está lidando com timestamps, lembrar que Unix epoch começa em 0, não em 1. E se precisa de números aleatórios com distribuição uniforme num range inteiro, prefira random.randint(a, b) em Python, que inclui ambos os extremos, ao invés de rand() % n em C, que introduz viés se o intervalo não dividir uniformemente o range do gerador. Esse viés é pequeno mas mensurável, e em criptografia é inaceitável.