Como transformar números em extenso — na prática
Pegar um número qualquer e escrever ele por extenso em português parece simples até você precisar lidar com valores grandes em documentos fiscais ou contratos. A regra básica é: você divide o número em classes (unidades, milhares, milhões, bilhões) e converte cada parte separadamente, ligando as classes com "mil", "milhões" e assim por diante. O problema é que o português brasileiro tem particularidades que a maioria dos conversores automáticos não trata bem.
let as por extenso: o que todo mundo procura
A busca por letras por extenso geralmente vem de alguém que precisa preencher um cheque, uma nota fiscal, um extrato ou um documento jurídico. O requisito é claro: o valor numérico tem que aparecer escrito por extenso, com acentuação correta, e sem erros. Um erro aqui pode invalidar um título executivo ou criar ambiguidade contratual. O processo manual funciona assim. Você pega o número, por exemplo 1.456.789,32, e decompõe: um milhão, quatrocentos e sessenta mil, setecentos e oitenta e nove reais e trinta e dois centavos. Percebe que o "e" aparece em lugares específicos? Ele entra entre as centenas e as dezenas quando a dezena não é zero. "Quatrocentos e sessenta" — sim, o "e". Mas "quinhentos e oito" também leva "e". Já "quatrocentos oitenta" não leva, porque oitava casa é zero e a regra muda quando a dezena é exata.
Isso é mais confuso do que parece. Eu passei semanas arrumando scripts de conversão automática e descobri que o maior problema não é a regra em si, mas os casos limite. Por exemplo: o número 110. A maioria dos converters errados gera "cento e dez" em vez de "cento e dez" — espera, esse está certo. O erro real aparece em 101: alguns geram "cem e um", quando o correto é "cento e um". "Cem" só existe quando é exatamente 100. A partir de 101 vira "cento" com o suffixo adequado. Isso parece besteira, mas em um sistema que processa milhares de notas fiscais por dia, um erro desses se repete milhões de vezes.
regras que poucos explicam direito
O primeiro erro comum que eu vejo todo mundo cometer é tratar o "1.000" como se fosse sempre "mil". Certo. Mas 2.000 é "dois mil". 1.001 é "mil e um". E 1.000.000 é "um milhão", não "milhão" — a forma correta no plural é "milhões", mas o singular mantém o "um" antes: "um milhão", nunca "milhão" sozinho. Já vi gente escrever "dois milhão" em contrato e o documento voltar para retificação. Outro ponto cego: a conjunção "e". Ela aparece obrigatoriamente entre a classe de milhares e a de unidades quando a classe de milhares não termina em zero. Exemplo: 1.001 = "mil e um". Mas 1.500 = "mil quinhentos" — sem "e". E 1.000.001 = "um milhão e um". A lógica é: o "e" liga classes apenas quando a classe anterior não é redonda. Quando é redonda, não precisa. Isso é consistente na norma culta, mas a maioria dos programadores que escrevem um conversor simples esquece dessa regra condicional.
Tem ainda a questão dos centavos. O padrão é usar "centavos" no plural para qualquer valor acima de 1. Quando é exatamente 1 centavo, diz-se "um centavo". Valores como 1,01 viram "um real e um centavo". Já 1,10 vira "um real e dez centavos". O erro típico de converter automatizado é deixar o "e" de fora nos centavos ou usar "centavo" no plural indiscriminadamente.
👉 Clique no botão abaixo para saber mais sobre o assunto!
ferramentas e como eu as uso
Para quem precisa de uma solução prática, existem várias bibliotecas open source. No Brasil, a mais usada é a num2letra (disponível via Composer para PHP) ou a money-to-text para Python. Se você está no .NET, o pacote Moq não serve — esquece. O pacote correto é o Numerals ou a implementação própria baseada na norma da Receita Federal. Eu configurei um script em Python que usa a biblioteca num2words com o parâmetro lang='pt-BR'. O resultado é bom para a maioria dos casos, mas tem uma falha conhecida: ele não separa corretamente reais de centavos em todos os formatos. Para resolver, eu divido o valor em duas partes — inteira e decimal — antes de passar para a conversão, e depois monto a string manualmente com "reais" e "centavos" conforme a gramática.
Em PHP, o composer install laravel/num-to-words funciona bem, mas exige que você trate o caso dos milhõezinhos manualmente quando o valor ultrapassa 999.999. Eu criei um wrapper que chama a função do Laravel e depois aplica uma regex para corrigir as junções que ficam erradas — tipo quando o gerador deixa de pôr o "e" entre milhões e milhares.
edge case que me custou duas horas
Uma vez eu recebi um lote de 3.000 notas fiscais para geração automática. O sistema estava funcional, mas um arquivo com valor 1.000.000,00 gerou "um milhão reais" em vez de "um milhão de reais". O bug estava na concatenação: o código colocava "reais" diretamente após "milhão" sem a preposição "de". A correção foi simples — adicionar uma verificação: quando a parte inteira é exatamente múltiplo de um milhão e a parte decimal é zero, insere-se "de" entre "milhão/milhões" e "real/reais". Outro problema que encontrei: valores como 1.500,00 geravam "mil e quinhentos reais" — com um "e" sobrando. A regra diz que quando a classe dos milhares é exata (1.000) e a classe das unidades também é exata (500), não há "e" entre elas. O "e" só entra quando há uma lacuna, como em 1.001 ("mil e um"). A correção foi adicionar uma condição: se a parte dos milhares for divisível por 1.000 e a parte restante for divisível por 100, não insere "e".
limitações e quando confiar no processo manual
Nenhuma ferramenta automatizada é 100% confiável em todos os cenários. Especialmente quando o valor ultrapassa bilhões, a ambiguidade aumenta. Números como 1.234.567.890,12 geram strings enormes e propensas a erros de concordância. O recomendável nesse caso é fazer uma revisão manual ou usar um validador de dupla entrada — um conversor gera, outro valida, e você compara o output. Se o seu contexto é um documento legal de alto risco, o ideal é usar uma ferramenta certificada ou um serviço que siga a tabela oficial do BACEN para escrita por extenso de valores em reais. Eles mantêm atualizações conforme as mudanças na norma — e sim, a norma mudou em 2009 com o Acordo Ortográfico, e alguns conversores antigos ainda usam "milheiro" em vez de "milhar" em certos contextos obsoletos.
Para uso interno, rotineiro, em volume baixo, um script com a lógica correta de junção e a validação manual dos casos extremos resolve. Para produção em larga escala, invista em uma biblioteca mantida ativamente e um suite de testes unitários que cubra pelo menos os valores entre 1 e 100.000, os múltiplos de mil, os milhões e os casos de transição como 1.000, 1.001, 10.000, 100.000, 1.000.000 e 1.000.001. Cobertura de testes assim reduz drasticamente a chance de um erro passar despercebido.