Achei uma planilha quebrando todo dia por causa disso
O problema que eu encontrei na prática foi com números grandes demais para fatoração manual. Tinha um usuário que precisava calcular o MDC de dois números primos entre si como 987654321 e 555111000. A tentativa de fatorar cada um separadamente levou mais de meia hora e ainda assim deu errado porque um dos números tinha fatores que eu não tinha identificado direito na primeira tentativa. A solução real é o algoritmo de Euclides, que resolve isso em segundos.
como fazer o máximo divisor comum de verdade
O método mais confiável que existe é o algoritmo euclidiano. Você divide o maior número pelo menor, pega o resto e repete o processo usando o divisor anterior e o resto. Quando o resto chegar a zero, o último divisor válido é o MDC. Pegamos os números 252 e 105. Dividimos 252 por 105 e o resto é 42. Agora dividimos 105 por 42, resto 21. Depois dividimos 42 por 21, resto zero. O último divisor foi 21, então o MDC de 252 e 105 é 21. Esse processo inteiro levou três divisões. Fatoração primária levaria muito mais tempo para números maiores.
O algoritmo funciona porque o MDC de dois números não muda se você substituir o maior pelo resto da divisão. Isso é basicamente a propriedade matemática que sustenta tudo. A gente prova isso facilmente: qualquer divisor comum a e b também divide o resto de a dividido por b, e vice-versa. Então o conjunto de divisores comuns permanece idêntico em cada passo.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Versão recursiva e otimizações
Se você for implementar isso num código, a versão recursiva é quase sempre mais limpa. A lógica é simples: se o resto for zero, retorna o divisor. Se não, chama a função de novo com o divisor e o resto. Em Python, isso fica com duas ou três linhas. Precisão com números gigantes: quando você trabalha com números acima de 10^18, a implementação precisa usar aritmética de múltipla precisão ou bibliotecas como GMP no C. Números normais de 64 bits já estouram em alguns casos reais de criptografia.
Pitfall comum: muita gente esquece que o MDC de números negativos segue a mesma lógica, mas o resultado é sempre positivo por definição. Se você passar valores negativos sem tratar isso, pode terminar com um MDC negativo em algumas implementações ingênuas. Resolva isso aplicando valor absoluto nos dois números antes de começar. Também tem o caso dos números primos entre si. Se o MDC der 1, os números são coprimos. Isso acontece com frequência em problemas de criptografia RSA, onde você precisa garantir que dois números não compartilhem nenhum fator. Testar coprimalidade é literalmente calcular o MDC e ver se o resultado é 1. Não existe atalho significativo pra isso além do próprio algoritmo euclidiano.
Quando o euclidiano não é suficiente
O algoritmo de Euclides padrão é eficiente, mas para cálculos repetidos em larga escala existem variantes mais rápidas. O algoritmo euclidiano binário, às vezes chamado de Stein, evita divisões e usa apenas subtrações e deslocamentos de bit. Em hardware com multiplicação cara mas deslocamento barato, isso pode ser significativamente mais rápido. A desvantagem é que a lógica é um pouco mais complexa de implementar corretamente. Para números extremamente grandes, como os usados em TLS e protocolos de segurança, o método de Euclides acelerado com radix transform é o padrão. Ele divide o problema em blocos menores e processa em paralelo. Implementações como as do OpenSSL usam isso internamente.
Um exemplo prático que eu uso frequentemente
Na minha rotina de trabalho, eu calculo MDC frequentemente quando preciso simplificar frações com números que vieram de medições experimentais. O problema é que essas medições vêm com erros e os números racionais resultantes às vezes são muito grandes. Eu rodo o euclidiano direto no calculador e pronto. Não tem jeito mais rápido para dois números de cada vez. Se você tiver muitos pares pra processar, aí vale a pena escrever um script. O tempo médio de cálculo para números de até 30 dígitos num computador moderno fica na casa dos microssegundos. A limitação real é o tempo de escrita do código, não a execução em si.