Introdução: por que a pergunta sobre módulo é tão popular?
\n\nSe você já escreveu código em Rust e lidou com números negativos, certamente já se perguntou: "Onde está a função de módulo?". No Stack Overflow, essa pergunta acumulou milhares de visualizações, e não é à toa. O problema é que o operador % em Rust não é módulo (modulus), mas sim o resto da divisão (remainder). A diferença é sutil, mas crítica, especialmente em algoritmos, criptografia ou trabalho com estruturas cíclicas.
Neste artigo, vamos entender a diferença entre o módulo matemático e o resto, como o Rust lida com números negativos e como escrever sua própria função para calcular o módulo verdadeiro. O artigo é voltado para iniciantes, mas também será útil para desenvolvedores experientes que desejam revisar o assunto.
\n\nResumo do conteúdo
\n- \n
- O que é módulo e resto: diferença matemática \n
- Por que
%em Rust não é módulo \n - Como escrever uma função de módulo em Rust \n
- Exemplos da vida real: índices cíclicos e hashes \n
- Conclusões e dicas práticas \n
Matemática: módulo vs resto
\n\nVamos começar pela base. Em matemática, módulo (modulus) é uma operação que retorna um número não negativo, menor que o divisor. Por exemplo:
\n- \n
7 mod 3 = 1(7 dividido por 3 tem resto 1) \n -7 mod 3 = 2(porque -7 = 3 * (-3) + 2) \n
Resto da divisão (remainder) é o que sobra após a divisão inteira. Na maioria das linguagens de programação (C, C++, Java, Rust), o operador % retorna exatamente o resto, que pode ser negativo se o dividendo for negativo. Exemplo:
- \n
7 % 3 = 1(coincide) \n -7 % 3 = -1(em Rust, porque -7 / 3 = -2, resto -1) \n
Para que serve isso? Imagine que você está programando um relógio: horário de 0 a 23. Se agora são 22 horas e você adiciona 5 horas, obtém 3 horas da manhã. Isso funciona com módulo: (22 + 5) mod 24 = 3. Mas se usar o resto, com valores negativos tudo quebra. Por exemplo, (-3) % 24 em Rust resulta em -3, e não 21.
Por que o operador % em Rust é remainder
\n\nEm Rust, o operador % é definido como resto da divisão. Isso está documentado e é o comportamento da biblioteca padrão. A razão é histórica: é assim em C e em muitas outras linguagens. Rust segue o princípio "explícito é melhor que implícito", mas aqui os iniciantes frequentemente caem em uma armadilha.
fn main() {\n println!("7 % 3 = {}", 7 % 3); // 1\n println!("-7 % 3 = {}", -7 % 3); // -1\n println!("7 % -3 = {}", 7 % -3); // 1 (sim, o sinal do divisor não afeta)\n println!("-7 % -3 = {}", -7 % -3); // -1\n}\n\nObserve: o sinal do resultado sempre coincide com o sinal do dividendo. Isso não é módulo. Para o módulo verdadeiro, o resultado deve ser sempre não negativo.
\n\nComo escrever uma função de módulo verdadeiro em Rust?
\n\nA biblioteca padrão do Rust não fornece uma função embutida para módulo (diferente do Python, onde % funciona como módulo). Mas escrever uma é muito simples. Aqui está a maneira mais comum — usando o resto com correção.
Função modulus para números inteiros
\n\nfn modulus(a: i32, b: i32) -> i32 {\n let r = a % b;\n if r < 0 { r + b.abs() } else { r }\n}\n\nfn main() {\n println!("modulus(7, 3) = {}", modulus(7, 3)); // 1\n println!("modulus(-7, 3) = {}", modulus(-7, 3)); // 2\n println!("modulus(7, -3) = {}", modulus(7, -3)); // 1 (módulo sempre não negativo)\n println!("modulus(-7, -3) = {}", modulus(-7, -3)); // 2\n}\n\nComo funciona: pegamos o resto a % b. Se for negativo, adicionamos o valor absoluto