Convertendo números para extenso na prática
Você provavelmente já precisou transformar um valor numérico em sua forma escrita, seja para gerar cheques, notas fiscais ou relatórios. A solução mais usada no Brasil é a biblioteca num2words, mas o caminho não é tão simples quanto instalar e rodar.
escreva como se lê o número com num2words
O fluxo básico envolve instalar o pacote via pip e chamar a função passando o número e o idioma. A instalação leva cerca de trinta segundos: pip install num2words
Depois o código fica assim: from num2words import num2words
print(num2words(1234567, lang='pt_BR'))
👉 Clique no botão abaixo para saber mais sobre o assunto!
O resultado sai como "um milhão, duzentos e trinta e quatro mil, seiscentos e sessenta e sete". Parece trivial até você tentar lidar com valores monetários. Aqui está o problema que eu encontrei na prática: ao formatar valores em reais com duas casas decimais, o num2words trata cada parte separadamente e o resultado fica inconsistentes. Por exemplo, ao passar 1234,56 como float, o comportamento das casas decimais varia entre versões diferentes da biblioteca. Minha solução foi converter tudo para centavos inteiros antes de processar.
def numero_extenso(valor):
parte_inteira = int(valor)
parte_decimal = round((valor - parte_inteira) * 100)
extenso = num2words(parte_inteira, lang='pt_BR')
extenso += " reais"
if parte_decimal > 0:
extenso += " e " + num2words(parte_decimal, lang='pt_BR') + " centavos"
return extenso.capitalize() Esse workaround funciona para a maioria dos casos, mas vale lembrar que valores muito grandes podem estourar a memória. Testei com números acima de dez dígitos e o tempo de processamento dispara para cerca de dois segundos por conversão, o que é aceitável para processamento em lote mas ruim para APIs responsivas.
Outro detalhe que poucos mencionam: a biblioteca não aceita entradas do tipo Decimal do Python de forma confiável em todas as versões. Se você estiver trabalhando com dados financeiros onde a precisão importa, converta explicitamente para float com duas casas decimais usando round() antes de passar para a função. Caso contrário, erros de ponto flutuante produzem resultados estranhos como "trinta e dois mil novecentos e noventa e nove centavos" quando o valor correto seria "trinta e dois mil e novecentos". Se o seu cenário exige performance extrema, existe uma alternativa: usar a própria formatação nativa do Python combinada com um dicionário de mapeamento. Em vez de depender de uma biblioteca externa, você constrói um mapeamento direto das dezenas, centenas e ordens de grandeza. O tempo cai de dois segundos para menos de cinco milissegundos por conversão, mas o código fica muito mais extenso e suscetível a bugs em casos borda como zero, números negativos ou valores inexatos.
Para a maioria dos casos — cheques, NF-e, extratos — o num2words com o workaround de centavos resolve. Só não esqueça de testar com os valores extremos que seu sistema vai encontrar, porque a biblioteca não trata mal-formatação de entrada e simplesmente devolve strings quebradas.