O que todo mundo precisa saber sobre representar frações
A representação de fração parece simples na teoria, mas na prática aparece em contextos muito diferentes uns dos outros. Tem a fração matemática que você vê no caderno, a fração computacional que o computador usa para calcular, e a fração visual que você precisa desenhar pro aluno entender. São três coisas totalmente distintas, e você vai ter problemas se tratar todas elas como a mesma. Vou começar pelo mais importante: como transformar uma fração em algo que seu programa ou sua planilha consiga operar sem destruir a precisão. A maioria das pessoas começa convertendo diretamente pra decimal com vírgula flutuante. Isso funciona até você precisar comparar 1/3 com 0,333333333 e perceber que já errou em algum ponto anterior do cálculo.
representacao de fracao em código
A forma mais confiável de fazer representacao de fracao num sistema é mantê-la como dois inteiros: numerador e denominador. Não tente ser criativo. O tipo fractions.Fraction do Python já faz isso nativamente, e se você estiver em outra linguagem, escrever uma classe básica com dois campos inteiros resolve 90% dos problemas. O problema real começa quando você precisa simplificar. O algoritmo padrão é o máximo divisor comum (MDC) de Euclides. Aqui vai o código que eu uso, sem enrolação:
def mdc(a, b):
while b:
a, b = b, a % b
return a
def simplificar(n, d):
if d == 0:
raise ValueError("denominador zero")
sinal = 1
if d 0:
n, d = -n, -d
g = mdc(abs(n), abs(d))
return n // g, d // g
Repare no ajuste de sinal. Se o denominador for negativo, você inverte ambos. Isso é algo que documentação amadora frequentemente esquece, e você passa duas horas debugando porque -1/3 e 1/-3 estão sendo tratados como valores diferentes em comparações. Outro detalhe que muita gente pula: validação de entrada. Se alguém passar float ao invés de inteiro, a fração já nasce errada. Um float como 0.1 representado como fração vira 1/10 apenas se você usar Fraction(0.1).limit_denominator(1000000). Do contrário, você pega a representação binária imperfeita do float e transforma num monte de lixo racional.
quando a fração exata não é suficiente
Existe um cenário onde frações exatas explodem em tamanho e travam tudo. É quando você soma várias frações com denominadores primos grandes entre si. O denominador comum cresce exponencialmente. Eu tive um caso específico num projeto de engenharia onde estávamos somando tolerâncias de peças fabricadas em lotes diferentes, cada uma com frações como 7/23, 13/41, 19/67. O denominador comum ficou com 63 dígitos. O Python conseguiu calcular, mas levou 4 minutos num notebook comum. A solução que eu adotei foi limitar o denominador máximo usando limit_denominator(max_denominator=109). Você perde precisão absoluta, mas ganha velocidade e memória. No contexto daquela aplicação, a margem de erro que entrou era da ordem de 10^-10, completamente dentro da tolerância aceitável. Trocar exatidão por viabilidade é uma decisão comum em engenharia numérica, não um defeito do método.
representação visual pra ensino
Se o seu objetivo é didático, a fração precisa ser algo que o olho consiga processar. O modelo mais usado é o modelo de área: desenhar um círculo ou retângulo dividido em partes iguais e pintar as que representam o numerador. Parece óbvio, mas tem uma armadilha que eu vejo todo mundo cair. O problema é que alunos confundem facilmente frações com o mesmo valor numérico quando desenhadas de formas geométricas diferentes. 2/4 de um círculo pintado é visualmente idêntico a 1/2 do mesmo círculo, mas se você pintar 2/4 de um quadrado e 1/2 de outro quadrado de tamanhos diferentes, a comparação falha. Sempre use a mesma unidade de referência quando for fazer comparação visual.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Eu resolvi isso criando uma função que normaliza o tamanho do bloco antes de desenhar. Basicamente, você converte todas as frações pro mesmo denominador e desenha o mesmo número total de divisões. Assim 2/4 e 1/2 ficam lado a lado com exatamente 4 fatias cada, duas pintadas em ambos os casos. A igualdade fica visível, não apenas declarada.
frações mistas e o problemão da conversão
Fração mista é aquele formato tipo 2 1/3 que todo mundo aprende no fundamental e depois abandona. Em programação, frações mistas são pesadelas porque a notação ambígua quebra parsers simples. O espaço entre o inteiro e a parte fracionária é interpretado de formas diferentes dependendo da biblioteca. Se você precisa lidar com frações mistas, converta pra imprópria antes de qualquer operação. 2 1/3 vira 7/3. A conta fica mais fácil, a comparação fica direta, e depois você converte de volta só pra exibição. O algoritmo é trivial: multiplique o inteiro pelo denominador, some com o numerador, e o denominador permanece.
def para_mista(n, d):
if d == 0:
raise ValueError("denominador zero")
sinal = "-" if (n < 0) != (d 0) else ""
n, d = abs(n), abs(d)
inteiro = n // d
resto = n % d
if inteiro == 0:
return f"{sinal}{resto}/{d}"
if resto == 0:
return f"{sinal}{inteiro}"
return f"{sinal}{inteiro} {resto}/{d}"
limitações que ninguém gosta de ouvir
Frações exatas não são uma bala de prata. Elas funcionam bem quando os números são pequenos e os denominadores têm fatores primos limitados. Quando você trabalha com medições físicas reais — coisas que vêm de sensores, digitalizações, ou qualquer fonte analógica — a fração exata é um mito. O dado de entrada já é aproximado, e transformar isso em fração dá uma falsa sensação de precisão. Em aplicações financeiras, frações normais também dão problema. Divisões de moeda precisam de arredondamento com regra específica, e frações exatas não trazem esse mecanismo embutido. Nesses casos, usar casas decimais fixas (tipo Decimal com precisão controlada) é mais adequado, mesmo que pareça menos "puro" conceitualmente.
E tem um terceiro ponto: impressão. Converter uma fração gigante pra string legível é mais caro do que parece. Uma fração com numerador e denominador de 100 dígitos cada demora cerca de 2 segundos pra ser formatada como texto. Se você precisa renderizar milhares delas na tela, considere manter a fração interna e só converter pra decimal na exibição final.
resumo prático
Se você quer representacao de fracao num sistema, use inteiros com MDC para simplificar. Valide entrada. Limite o denominador quando o custo de precisão exceder o benefício. Evite frações mistas em processamento. E saiba quando abandonar frações exatas em favor de aritmética de ponto flutuante controlada ou Decimal. Não existe solução única que funcione em todos os cenários, e reconhecer isso economiza mais tempo do que qualquer otimização prematura.