Um milhão, um mil e um ou um milhão mil e um?
21 de Maio de 2010, 0:00 - sem comentários aindaPara os preguiçosos:
O projeto de que trato aqui é um conversor de números para sua representação “por extenso”. Se você chegou aqui e não quer ter o trabalho de ler, apenas achar o código, siga este link: código (ou acesso o projeto no google code). Se, por outro lado, estiver em busca de explicações para fazer o seu próprio conversor ou curioso sobre como este conversor aí em cima funciona, leia o resto deste post.
Para os curiosos:
O título é esquisito, mas a dúvida era essa. O problema surgiu quando, num dos relatórios do sistema, o cliente exigiu que os valores fossem escritos de forma numérica (fácil, o NumberFormat dá conta que é uma beleza) seguidos do valor por extenso. Pensei com meu botões: não tem problema, TODO MUNDO já precisou disso um dia, deve ter DÚZIAS de conversores para números por extenso vagando pelo labirinto de Falken. Basta escolher o mais bonitim e boas!
Na verdade a tarefa nem era minha. Caiu pra mim quando surgiu o primeiro bug. A classe que tinham usado funcionava bem, contanto que o número fosse redondo ou pequeno. “Um milhão de reais” ele disse quando pedi pra converter 1.000.000,00. Mas logo depois me cospe “Um milhão e três de reais” pra 1.000.003,00. Hein? Mas peraí, isso eu conserto, vá… Só que o próximo número piorou: “Um milhão e seiscentos e cinquenta mil e novecentos e dez reais”. Pera lá! Tem E demais aí!.
A primeira coisa que pensei foi em achar outro conversor. Doce ilusão. Existir até existem. Vários (ou melhor, várias cópias do mesmo, já que parecem ser todos baseados no mesmo código original). Mas nenhum funciona.
Quer dizer, funcionam… Se você usar os números de teste que o autor usou! (Quem gosta disso pode fazer disto um “caso” para test-driven design, ou o que valha). Saindo um pouco do que o autor tinha em mente, a coisa desanda.
Nesse ponto eu não tinha mais escolha: teria de implementar o meu próprio conversor. Bom, que os outros estavam errados eu sabia, mas e qual a forma correta de se escrever por extenso? Depois de muita discussão e nenhum acordo, decidimos: Vamos consultar uma gramática!
Na biblioteca, pegamos logo 3 gramáticas. Nenhuma, claro, concordava com a quantidade de “e” que o sujeito usou. Alias, nenhuma delas concordava entre si. Uma, a mais antiga, pregava o uso de vírgulas a torto e a direito:
um bilhão, cento e vinte milhões, duzentos e três mil, cento e quarenta e sete.
A outra era categórica: depois de mil não! Só depois dos “ãos” é que tem vírgula:
um bilhão, cento e vinte milhões, duzentos e três mil cento e quarenta e sete.
E por último, uma que se dizia de acordo com o novo acordo ortográfico (que não tratou nem de números nem de vírgulas, mas que de alguma forma afetava a opinião do autor a respeito) abominava vírgulas:
um bilhão cento e vinte milhões duzentos e três mil cento e quarenta e sete.
Assim fica difícil, né? Em nosso auxílio veio uma ótima e hiper didática revisora de texto que passava pelo local:
Vírgulas servem para separar os elementos numa lista. No caso dos números, use para separar cada grupo de unidade, milhar, milhão, etc. (nesse ponto a gente, das exatas, anota: uma vírgula a cada potência de 1000). Mas elas não são absolutas, e podem ser omitidas se for para aumentar a clareza. Pense na clareza do texto e escolha a forma que melhor lhe convém. Depois de escolhido o melhor jeito, procure uma gramática que concorde com você e use ela como bibliografia!
Pra mim, esse conselho foi genial. E de certa forma resolveu nosso problema: bastava escolher o mais fácil de implementar e depois procurar uma gramática que nos apoiasse.
Acabei me guiando por 8 regrinhas, que definiram como implementar meu conversor:
- números abaixo de 20 tem nome próprio;
- de 21 a 99 os números são formados por DEZENA “e” UNIDADE (exemplo: “trinta e cinco”);
- dezenas redondas não tem nada depois (20 -> “vinte”, e não “vinte e zero”);
- 100 tem nome próprio: cem;
- números maiores que 100 são compostos por CENTENA “e” DEZENA ["e" UNIDADE];
- acima de 1000 agrupa-se os números em blocos de 3 dígitos (potências de 1000), que são representados como se fossem números menores do que 1000 acrescidos do sufixo representando a potência de mil apropriada (mil, milhão, etc);
- os grupos são concatenados por vírgula;
- A ultima concatenação é feita por “e” (“um milhão e 200 mil”);
- A ultima concatenação é omitida (ou substituída por vírgula) caso o ultimo grupo seja maior que 100 e não seja múltiplo e 100 (“mil[,] duzentos e cinquenta”)
- o “um” em frente ao descritor de grupo “mil” é opcional e deve ser parametrizável (“mil e um” e “um mil e um” são igualmente aceitáveis);
- Ao acrescentar a unidade (por exemplo “reais”) usa-se o prefixo “de” antes da unidade caso o último sufixo seja de milhão ou maior (“dez milhões de reais”, mas “dez mil reais”).
Com essas regras a implementação foi quase direta. Primeiro criei uma função para as unidades:
String unidades(int n) {
return UNIDADES[n];
}
Em seguida as dezenas:
String dezenas(int n) {
if (n < UNIDADES.length) return unidades(n);
int unidade = n % 10;
n = n / 10;
return DEZENAS[n] + " e " + unidades(unidade);
}
depois tratei a exceção da regra 3:
String dezenas(int n) {
. . .
String unidadeStr = "";
if (unidade != 0) {
unidadeStr = " e " + unidades(unidade);
}
return DEZENAS[n] + unidadeStr;
}
E seguindo as regras uma a uma cheguei no resultado final, que pode ser visto no google code. Ainda não está perfeito, e ainda quero brincar bastante com esse conversor, então deixem suas sugestões,seja aqui, seja como “bug” no google code, que eu implemento, caso dê tempo (e ânimo).
Curling
3 de Março de 2010, 0:00 - sem comentários aindaSeguindo a idéia desse cara aqui, decidimos treinar o Tomtom desde cedo no Curling:
Caralhos Alados
19 de Janeiro de 2010, 0:00 - sem comentários aindaHoje em dia fazem de tudo pras crianças brincarem, mas caralho de asa foi o primeiro que eu vi…
Eu não fiz isso!
15 de Janeiro de 2010, 0:00 - sem comentários aindaPor sugestão do Bguno, mais um lolGPS…
Canibais
4 de Janeiro de 2010, 0:00 - sem comentários aindaMais ou menos um ano atrás eu estava passeando por uma banca ou livraria, não lembro bem e vi uma seção de livros de bolso baratinhos. Como sempre, dei uma fuçada e além de um livro do Rousseau (Contrato Social, que ainda estou pela metade) achei esse: Canibais, do David Coimbra.
Só que desde que comprei o meu netbook1, a leitura praticamente parou! Tentaram me convencer a usá-lo como leitor de e-book, mas é simplesmente impossível: assistir filmes é BEM mais fácil! Acho que assisti de tudo, desde filme de arte iraniano até comédia de Bollywood (ok, tentei ver um tal de All the Best, mas não dei conta de terminar! Novela das sete dá de 10 a zero naquilo em termos de roteiro!) Aí nesse final de ano os seriados de assistir no banheiro2 secaram, só voltam ano que vem, ou quem sabe, temporada que vem… A solução foi deixar o netbook de lado e voltar à leitura, em livros… de papel… árvores mortas… Primeiro, pra acostumar o cérebro, já meio enferrujado depois de tanto tempo, os quadrinhos, com o excelente Nova York, do Will Eisner. Depois, o que estava mais a mão: Canibais.
Bom, voltando a quando eu comprei… Conheci o David Coimbra numa dessas listas de discussão na internet. “Conheci”, na verdade, entre aspas. Ele nem deve saber quem eu sou Mas ele volta e meia mandava umas crônicas, e quem diz que não se fazem mais cronistas como antigamente, é porque não conhece o David Coimbra. Ou conhece, e sabe que mesmo antigamente não haviam cronistas como ele
Eu nem sabia que ele escrevia romances, pra mim eram as crônicas no Zero Hora, vez ou outra encadernadas todas juntas, em forma de livros. Então quando bati o olho no livro, nem pensei, comprei logo. “Nem que seja pra mandar um trocado pro David Coimbra”, pensei, “em troca de todas as crônicas que ele mandava, de graça, no nosso email”. Se fosse ruim, não tinha importância, estava pagando pelo que já lera. Se fosse bom, eu estava no lucro.
E lucrei! Incrível, não sei como não me odeio por ter enrolado tanto pra ler! Desde minha tenra infância, apresentado aos romances históricos pelos Césares do Allan Massie3, depois as sagas do Cornwell, e por fim o belíssimo A Catedral do Mar. Então sempre passei meu tempo imaginando: qual seria o cenário ideal pra um romance histórico brasileiro? As bandeiras? O descobrimento? Ou seria lusitano demais?
David Coimbra achou o cenário ideal numa porto alegre do segundo império, com sua burguesia nascente, seus conflitos étnicos, seus personagens característicos (desde prostitutas a chefes de polícia), e também com seu crime mais famoso. É nesse cenário que David Coimbra colocou um trio de amigos: um sapateiro introspecto, quase intelectual, um padeiro gorducho e bonachão, e um anspeçada4 boa vida com seu cão. Em torno desse trio, toda porto alegre oitocentista circula para desvendar um crime que chocou e envergonhou a cidade. Um crime que fez de todos (ou quase todos) os porto alegrenses, Canibais.
- Por sinal, devo um post sobre o ubuntu 9.10 nele. Uma dica: VALE A PENA.
- i.e. Two and a Half Men, How I met You Mother (que mereceria um post a parte talvez), The Big Bang Theory, South Park…
- ou talvez antes disso, com um romance que nunca mais vou lembrar de quem era, sobre um padre disfarçado em uma Cambridge medieval, investigando não-sei-mais que crime e que se depara com uma encarnação de cristo na forma de mulher, ou algo assim… Bem falando desse jeito parece um romance esotérico, e talvez fosse… eu era jovem e precisava do dinheiro…
- também tive de recorrer ao labirinto de falken pra saber exatamente o que era…