Introdução
Seguindo a ideia do post [1] sobre o algoritmo geral para se escrever números em extenso, resolvi fazer a versão em python do algoritmo. Aqui no blog tem a versão em C [2] para quem desejar conhecer.
O código
Salve como dExtenso.py
#!/usr/bin/env python # -*- coding: utf-8 -*- # # [dExtenso.py] # Implementa o algoritmo geral de escrita # por extenso de um número qualquer. # # [Autor] # Marcos Paulo Ferreira (Daemonio) # undefinido gmail com # https://daemoniolabs.wordpress.com # # Versão 1.0 by daemonio @Thu Sep 12 22:22:06 BRT 2013 # Versão 1.1 by daemonio @Sat Dec 20 23:41:50 BRST 2014 # + consertado bug no "cem" class dExtenso(): trioextenso=() classextenso=() def __init__(self): self.trioextenso=( ("dummy","um","dois","três","quatro","cinco","seis","sete", "oito","nove"), ("dez","onze","doze","treze","quatorze","quinze","dezesseis", "dezessete","dezoito","dezenove"), ("dummy","dummy","vinte","trinta","quarenta","cinquenta", "sessenta","setenta","oitenta","noventa"), ("dummy","cento","duzentos","trezentos","quatrocentos", "quinhentos","seiscentos","setecentos","oitocentos", "novecentos")) self.classextenso=( "dummy","mil","milh","bilh","trilh","quatrilh", "quintilh","sextilh","septilh","octilh", "nonilh","decilh","undecilh","duodecilh", "tredecilh","quatordecilh","quindecilh", "sexdecilh","setedecilh","octodecilh", "novedecilh","vigesilh" ) def escrever_trio_extenso(self, trio): """ Retorna um trio por extenso. Entrada: trio na forma de string. Retorno: trio em extenso. """ saida=[] if trio == '100': # Erro antigo aqui. Consertado usando "return" return 'cem' elif trio == '000': return 'zero' else: c, d, u = trio c, d, u = int(c), int(d), int(u) if c != 0: saida.append(self.trioextenso[3][c]) if d == 1: saida.append(self.trioextenso[1][u]) else: if d != 0: saida.append(self.trioextenso[2][d]) if u != 0: saida.append(self.trioextenso[0][u]) return ' e '.join(saida) def nao_e_ultimo_trio(self, totalTrios, contador): """ Retorna verdadeiro se o trio indicado pelo contador não é o último (isso é, não é o mais à direita). Entrada: Número total de trios e o contador. Retorno: Verdadeiro se o trio NÃO é o último e falso caso contrário. """ return contador < (totalTrios - 1) def trio_a_esquerda_eq_zero(self, trioLista, contador): """ Retorna verdadeiro se o trio à esquerda do trio indicado pelo contador é igual a zero. Entrada: Os trios em forma de Lista e o contador. Retorno: Verdadeiro se o trio à esquerda do contador for zero e falso caso contrário. """ # Contador igual a zero indexa o elemento mais à direita, # por isso devemos acrescentar tamanho da lista. t = len(trioLista)-1 return trioLista[t-contador-1] == '000' def getExtenso(self, num, quebradelinhas=0): """ Algoritmo principal. Recebe um número na forma de string e retorna sua escrita em extenso. Entrada: Número na forma de string e uma flag que, se tiver o valor 0 (zero), o extenso é retornado em uma só linha. Um valor 1 (um) faz o extenso ser quebrado em várias linhas. Retorno: O número de entrada em extenso na forma de string. """ # Remove os zeros iniciais e faz padding # para números com quantidade de algarismos # não múltipla de 3 num = num.lstrip('0') pad = 3 - len(num)%3 if pad < 3: num = '0'*pad + num it = iter(num) trioLista = [ ''.join([a,b,c]) for a, b, c in zip(it, it, it)] if len(trioLista) > len(self.classextenso): raise IndexError,'Número muito grande' contador=0 saida='' extensofinal='' for trio in reversed(trioLista): trioInt=int(trio) if trioInt > 0: saida = self.escrever_trio_extenso(trio) if contador > 0: saida = saida + ' ' + self.classextenso[contador] if contador > 1: if trioInt > 1: saida = saida + 'ões' else: saida = saida + 'ão' if quebradelinhas == 0: if self.nao_e_ultimo_trio(len(trioLista), contador): if self.trio_a_esquerda_eq_zero(trioLista, contador): saida = ' e ' + saida elif trioInt >= 100: saida = ', ' + saida else: saida = ' e ' + saida else: saida = saida + '\n' extensofinal = saida + extensofinal contador = contador + 1 return extensofinal.rstrip('\n') if __name__ == '__main__': import sys argc = len(sys.argv) if argc < 2: print '[uso] %s <numero>' % (sys.argv[0]) else: n = dExtenso() # Valor 1 em quebradelinhas faz o extenso de # cada trio ser em uma linha separada. print n.getExtenso(sys.argv[1], quebradelinhas=0)
Uso
Você pode utilizar o código diretamente no terminal ou criar instâncias da classe no seu código python. Para rodar via terminal, digite:
$ chmod +x dExtenso.py $ ./dExtenso 9977700 nove milhões, novecentos e setenta e sete mil, setecentos
No próprio código fonte do módulo há um exemplo da criação de uma instância. A seguir mais um exemplo:
$ python >>>import dextenso >>>ext = dextenso.dExtenso() >>>print ext.getExtenso('9977700') nove milhões, novecentos e setenta e sete mil, setecentos >>>print ext.getExtenso('8923718789312379818792379123887172397891371', quebradelinhas=1) oito tredecilhões novecentos e vinte e três duodecilhões setecentos e dezoito undecilhões setecentos e oitenta e nove decilhões trezentos e doze nonilhões trezentos e setenta e nove octilhões oitocentos e dezoito septilhões setecentos e noventa e dois sextilhões trezentos e setenta e nove quintilhões cento e vinte e três quatrilhões oitocentos e oitenta e sete trilhões cento e setenta e dois bilhões trezentos e noventa e sete milhões oitocentos e noventa e um mil trezentos e setenta e um
Passando quebradelinhas=1, cada extenso de um trio vem em uma linha separada.
Referências
Números Por Extenso: Algoritmo Geral by Daemonio (Acessado em: Setembro/2013)
https://daemoniolabs.wordpress.com/2012/06/24/numeros-por-extenso-algoritmo-geral/
Biblioteca em C: Números por Extenso by Daemonio (Acessado em: Setembro/2013)
https://daemoniolabs.wordpress.com/2012/10/20/biblioteca-em-c-numeros-por-extenso/
Impressionante que em python tudo que você procura tem online.
Muito obrigado, XD.
Só uma sugestão, colocar no gist: https://gist.github.com/anonymous/d760379ce070d56e8f1c124eb8732bde
Python realmente é muito poderosa. Obrigado pela sugestão e divulgação do código.
ta errado
onde tem erro, amigo?
abraço
Em python 3.7 corrigir:
raise IndexError,’Número muito grande’
por:
raise NameError(‘Numero muito grande!’)
Ok. O código foi escrito para python2.7, devem ter outras modificações para adequar o código à versão 3. Por enquanto vou deixar assim.