fractions no Python: números racionais

Publicado em: 31/07/2026
Tempo de leitura: 7 minutos
Gráficos de frações representando números racionais exatos no Python

Frações aparecem em receitas, proporções, escalas, música, probabilidades, conversões e algoritmos matemáticos. Usar float para representar 1/3 ou 2/7 produz aproximações, enquanto converter tudo para Decimal nem sempre resolve números periódicos. O módulo fractions no Python oferece a classe Fraction, que armazena numerador e denominador como inteiros e mantém cálculos racionais exatos.

Neste guia, você aprenderá a criar frações de inteiros, strings, Decimal e floats, simplificar valores, recuperar aproximações com limit_denominator(), formatar resultados e escolher entre Fraction, Decimal e float. O conteúdo complementa nossos artigos sobre float em Python, Decimal, inteiros, tipos de dados e formatação com f-strings.

O que é um número racional

Um número racional pode ser escrito como a razão entre dois inteiros, com denominador diferente de zero. Exemplos incluem 1/2, -7/3, 5 e 0.125. A classe Fraction conserva essa estrutura:

from fractions import Fraction

metade = Fraction(1, 2)
terco = Fraction(1, 3)

print(metade)
print(terco)

As instâncias são imutáveis e hashable, portanto podem ser usadas como chaves de dicionário e elementos de conjuntos.

Normalização automática

O construtor reduz a fração aos menores termos e mantém o denominador positivo.

from fractions import Fraction

print(Fraction(16, -10))  # -8/5
print(Fraction(20, 30))   # 2/3

O módulo usa máximo divisor comum para normalização. Não é necessário simplificar manualmente depois de cada operação.

Criando Fraction de strings

Strings são uma forma segura de preservar a intenção textual.

from fractions import Fraction

print(Fraction("3/7"))
print(Fraction(" -3 / 7 "))
print(Fraction("0.125"))
print(Fraction("7e-6"))

Desde o Python 3.12, espaços em torno da barra são aceitos. Valores decimais finitos viram razões exatas, como 0.125 = 1/8.

Construção a partir de float

Um float é convertido para sua representação binária exata, não necessariamente para a fração decimal que você imaginou.

from fractions import Fraction

print(Fraction(1.1))
# 2476979795053773/2251799813685248

A causa é a mesma discutida na documentação oficial sobre ponto flutuante: 1,1 não possui representação binária finita. Para representar exatamente onze décimos, use Fraction("1.1") ou Fraction(11, 10).

Fraction a partir de Decimal

Um Decimal finito é convertido exatamente:

from decimal import Decimal
from fractions import Fraction

valor = Fraction(Decimal("1.1"))
print(valor)  # 11/10

Essa conversão é útil quando uma entrada foi validada como decimal, mas o algoritmo precisa trabalhar com uma razão exata.

from_number() no Python 3.14

O Python 3.14 adicionou Fraction.from_number(). Ele aceita inteiros, racionais, floats, Decimal e objetos com as_integer_ratio(), mas não strings.

from fractions import Fraction

print(Fraction.from_number(5))
print(Fraction.from_number(2.25))

A conversão de float continua refletindo o valor binário exato. A nova API apenas torna explícita a expectativa de receber um objeto numérico.

Operações aritméticas exatas

from fractions import Fraction

a = Fraction(1, 3)
b = Fraction(1, 6)

print(a + b)  # 1/2
print(a - b)  # 1/6
print(a * b)  # 1/18
print(a / b)  # 2

Os resultados permanecem normalizados. Potenciação com expoente inteiro também funciona, inclusive com expoentes negativos quando a base não é zero.

Numerator e denominator

Os atributos de leitura expõem os componentes na forma reduzida:

valor = Fraction(42, 56)
print(valor.numerator)    # 3
print(valor.denominator)  # 4

O denominador é sempre positivo. O sinal fica no numerador.

Recuperando uma fração legível de um float

limit_denominator() encontra a aproximação mais próxima cujo denominador não ultrapassa um limite.

from fractions import Fraction

aproximacao = Fraction(1.1).limit_denominator()
print(aproximacao)  # 11/10

A documentação oficial de fractions também mostra a aproximação 355/113 para pi quando o denominador máximo é 1000.

from fractions import Fraction

pi_aprox = Fraction("3.141592653589793").limit_denominator(1000)
print(pi_aprox)  # 355/113

Escolhendo max_denominator

O limite deve refletir o problema. Em uma receita culinária, denominadores até 16 podem ser suficientes. Em uma aproximação científica, talvez sejam necessários milhares.

valor = Fraction("0.3332")
print(valor.limit_denominator(10))
print(valor.limit_denominator(1000))

Um limite alto melhora a aproximação, mas pode produzir razões difíceis de interpretar. Defina a tolerância e valide o erro resultante.

Verificando se a fração é inteira

Desde o Python 3.12, is_integer() indica se o denominador reduzido é 1.

print(Fraction(6, 3).is_integer())  # True
print(Fraction(7, 3).is_integer())  # False

Você também pode converter com int(), mas essa conversão trunca em direção a zero. Não use como teste de integralidade.

floor, ceil e round

Fraction integra-se às funções de arredondamento:

import math
from fractions import Fraction

valor = Fraction(7, 3)
print(math.floor(valor))
print(math.ceil(valor))
print(round(valor, 2))

round() usa empates para o par. Quando ndigits é fornecido, o resultado continua sendo Fraction.

Formatação com f-strings

Versões recentes do Python ampliaram a formatação. Desde 3.12, tipos de apresentação como f, e, g e porcentagem estão disponíveis.

from fractions import Fraction

valor = Fraction(1, 7)
print(f"{valor:.6f}")
print(f"{valor:.2%}")

Desde o Python 3.13, formatação sem tipo também suporta alinhamento, sinal, largura e agrupamento.

print(f"{Fraction(103993, 33102):_}")
print(f"{Fraction(3, 1):#}")

A flag # força a exibição do denominador, inclusive em valores inteiros.

Comparações e ordenação

Frações podem ser comparadas com inteiros, floats e Decimal, embora comparações com float reflitam sua aproximação binária.

valores = [Fraction(2, 3), Fraction(1, 2), Fraction(3, 4)]
print(sorted(valores))

Para regras exatas, normalize os tipos antes da comparação.

Frações em receitas e proporções

from fractions import Fraction

receita_base = Fraction(3, 4)
fator = Fraction(5, 2)
quantidade = receita_base * fator
print(quantidade)  # 15/8

Você pode separar a parte inteira e a fração restante para exibição amigável.

inteiro = quantidade.numerator // quantidade.denominator
resto = quantidade - inteiro
print(inteiro, resto)

Probabilidades exatas

Frações são úteis em espaços amostrais pequenos:

favoraveis = 6
possiveis = 36
probabilidade = Fraction(favoraveis, possiveis)
print(probabilidade)  # 1/6

Em modelos grandes, numeradores e denominadores podem crescer rapidamente. Para estatística numérica em escala, float e bibliotecas vetorizadas podem ser mais adequados.

Conversões de unidades

Fatores racionais evitam erros acumulados:

polegadas_por_pe = Fraction(12, 1)
pes = Fraction(5, 2)
polegadas = pes * polegadas_por_pe
print(polegadas)  # 30

Documente a unidade de cada valor. Exatidão numérica não impede misturar metros e centímetros incorretamente.

Crescimento de numerador e denominador

Operações repetidas podem criar inteiros enormes. A normalização reduz fatores comuns, mas não limita a magnitude.

valor = Fraction(1, 1)
for n in range(2, 50):
    valor += Fraction(1, n)
print(len(str(valor.numerator)))

Esse custo pode tornar Fraction mais lento e consumir memória. Em algoritmos aproximativos, limite o denominador em pontos controlados ou use outro tipo numérico.

Fraction versus Decimal

Use Fraction quando o valor é naturalmente uma razão e precisa permanecer exato, como 1/3, escalas ou probabilidades combinatórias. Use Decimal quando o domínio trabalha com casas decimais, dinheiro e regras de arredondamento.

Decimal representa 0.1 exatamente, mas 1/3 precisa ser arredondado conforme o contexto. Fraction representa 1/3 exatamente, mas 0.10 é reduzido para 1/10 e não conserva zeros significativos.

Fraction versus float

Float é muito mais rápido e integrado a NumPy, gráficos e bibliotecas científicas. Fraction é melhor para exatidão simbólica em volumes moderados.

Não converta para float no meio de um cálculo exato e depois volte esperando recuperar a razão original. Se a conversão for necessária para uma biblioteca, deixe-a na borda e documente a tolerância.

Serialização

JSON não suporta Fraction nativamente. Uma representação explícita evita ambiguidade:

registro = {
    "numerator": valor.numerator,
    "denominator": valor.denominator,
}

Outra opção é enviar a string "3/4", desde que o contrato da API descreva o formato. Não envie apenas um float quando a exatidão precisa sobreviver.

Validação de entrada

Capture ValueError para strings inválidas e ZeroDivisionError para denominador zero.

from fractions import Fraction


def ler_fracao(texto: str) -> Fraction:
    try:
        return Fraction(texto)
    except (ValueError, ZeroDivisionError) as erro:
        raise ValueError("Fração inválida") from erro

Imponha limites de tamanho em entrada não confiável. Inteiros com milhões de dígitos podem consumir recursos excessivos.

Testando cálculos racionais

assert Fraction(1, 3) + Fraction(1, 6) == Fraction(1, 2)
assert Fraction("0.125") == Fraction(1, 8)
assert Fraction(1.1).limit_denominator() == Fraction(11, 10)

Teste também sinais, denominador zero, parsing, formatação e limites de aproximação.

Erros frequentes

  • Criar Fraction(1.1) esperando 11/10.
  • Usar denominadores ilimitados em dados não confiáveis.
  • Escolher Fraction para dinheiro e perder a escala de centavos.
  • Converter para float cedo demais.
  • Interpretar int(fracao) como arredondamento.
  • Usar um max_denominator sem medir o erro.
  • Serializar apenas a aproximação decimal.
  • Ignorar o crescimento dos inteiros.

Boas práticas

  • Use inteiros ou strings para construção exata.
  • Prefira Decimal quando a escala decimal faz parte do contrato.
  • Defina limites de denominador conforme o domínio.
  • Mantenha Fraction dentro do núcleo exato do cálculo.
  • Valide entradas e tamanhos.
  • Serialize numerador e denominador explicitamente.
  • Meça desempenho em loops grandes.
  • Teste aproximações e casos negativos.

Conclusão

O módulo fractions no Python fornece aritmética racional exata com uma API integrada ao restante da linguagem. A classe Fraction normaliza automaticamente numerador e denominador, aceita várias formas de entrada, oferece aproximações controladas e suporta formatação moderna.

A escolha depende da natureza do problema. Frações preservam razões como 1/3; Decimal preserva valores decimais e regras monetárias; float privilegia desempenho e integração numérica. Quando o tipo representa corretamente o domínio, o código evita aproximações desnecessárias e produz resultados mais claros, verificáveis e fáceis de explicar.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Calculadora e documentos representando cálculos decimais precisos no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    Decimal no Python: cálculos precisos

    Aprenda Decimal no Python para cálculos exatos, dinheiro, quantize, arredondamento, contextos e validação sem erros de float.

    Ler mais

    Tempo de leitura: 8 minutos
    30/07/2026
    Código digital representando identificadores UUID únicos e ordenáveis no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    uuid no Python: IDs únicos e ordenáveis

    Aprenda uuid no Python: versões 4, 5, 6 e 7, validação, bancos de dados, IDs ordenáveis e cuidados de segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    30/07/2026
    Arquivos organizados representando armazenamento temporário seguro no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    tempfile no Python: arquivos temporários

    Aprenda tempfile no Python para criar arquivos e pastas temporárias com segurança, limpeza automática e suporte a Windows e Unix.

    Ler mais

    Tempo de leitura: 8 minutos
    29/07/2026
    Relógios representando fusos horários internacionais com zoneinfo no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    zoneinfo no Python: fusos horários

    Aprenda zoneinfo no Python para converter fusos, lidar com horário de verão, fold, UTC e tzdata sem erros de agendamento.

    Ler mais

    Tempo de leitura: 8 minutos
    29/07/2026
    Ícone de documentos duplicados representando cópia rasa e profunda no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    copy no Python: cópia rasa e profunda

    Aprenda copy no Python para criar cópias rasas, profundas e substituir campos sem compartilhar objetos mutáveis por engano.

    Ler mais

    Tempo de leitura: 8 minutos
    28/07/2026
    Monitor com busca binária e listas ordenadas no Python
    Bibliotecas e Módulos
    Foto de perfil de Leandro Hirt da Academify

    bisect no Python: listas sempre ordenadas

    Aprenda bisect no Python para manter listas ordenadas, encontrar intervalos e inserir valores com busca binária eficiente.

    Ler mais

    Tempo de leitura: 8 minutos
    27/07/2026