Neste artigo veremos como converter números decimais em romanos na linguagem de programação Java. Teremos também uma comparação com implementações em outras linguagens como PHP e Python.
O processo de conversão entre números decimais e romanos é bastante simples uma vez que se conhece o algoritmo. O primeiro passo é obter uma tabela com os símbolos romanos e os valores decimais correspondentes:
1000 M 900 CM 500 D 400 CD 100 C 90 XC 50 L 40 XL 10 X 9 IX 5 V 4 IV 1 I
Em seguida, divida o número decimal pelo valor decimal correspondente ao maior símbolo romano e considere apenas a parte inteira do resultado. Por exemplo, se o número decimal original for 3.449:
3449 / 1000 = 3.449 (parte inteira: 3)
Adicione ao número romano resultante a letra romana (M) multiplicada pela parte inteira (3), resultando em "MMM". Multiplique a parte inteira pelo valor decimal do romano (1000) e subtraia do valor original:
3449 - (3 * 1000) = 449
Os próximos números romanos da tabela (CM e D) são maiores do que o valor restante, por isso serão ignorados. Iremos direto para o numeral CD (400):
449 / 400 = 1,1225
Agora, acrescente CM ao número romano resultante: MMMCD. O valor restante é 449 - 400 = 49
.
Pularemos todos os números restantes que forem maiores que 49, indo para o XL (40):
49 / 40 = 1,225
Ficou fácil, não é? O número romano ganha de presente um XL: MMMCDXL. Agora, o resto é apenas 9, que corresponde exatamente ao romano IX:
9 / 9 = 1
Portanto, o número 3.449 convertido em algarismos romanos é MMMCDXLIX.
Implementação em Java
Como mencionado, a implementação é simples depois que o algoritmo é compreendido. O Java não seria Java se não tivéssemos uma classe, então, iniciaremos com a estrutura básica da classe:
public class NumerosRomanos { public static String converterEmRomanos(int decimal) { (...) } }
Optamos por um método static
para simplificar a invocação.
O número romano será retornado como String, o que é suficiente para a maioria dos casos.
Acima de tudo, não queremos complicar o nosso código mais do que o necessário.
Seguindo em frente, criaremos a representação da tabela de conversão:
public class NumerosRomanos { private static final int[] DECIMAIS = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; private static final String[] ROMANOS = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; (...) }
Desta vez, criamos dois arrays, um para os números decimais e outro para os romanos correspondentes.
Por que não usar um HashMap
?
Porque, como vamos iterar pelos valores da tabela, um HashMap, por ser desordenado, tornaria as coisas um pouco mais complicadas para nós.
Poderíamos ter utilizado um LinkedHashMap
, que é ordenado, mas mesmo assim, inicializar um Map em Java não é nada elegante e a nossa dupla de arrays será o bastante.
Agora, vamos finalmente ao método:
public static String converterEmRomanos(int decimal) { StringBuilder resultado = new StringBuilder(); (...) return resultado.toString(); }
Utilizamos um StringBuilder
em vez de uma String por ser mais eficiente, embora neste exemplo a diferença de desempenho não vá ser muito grande.
public static String converterEmRomanos(int decimal) { StringBuilder resultado = new StringBuilder(); for (int i = 0; i < DECIMAIS.length; i++) { (...) } return resultado.toString(); }
Aqui, iteramos pelos números decimais, mas a variável i
será útil também para acessar a lista de romanos.
import static java.util.Collections.nCopies; import static java.lang.String.join; (...) public static String converterEmRomanos(int decimal) { StringBuilder resultado = new StringBuilder(); for (int i = 0; i < DECIMAIS.length; i++) { int parteInteira = decimal / DECIMAIS[i]; decimal -= DECIMAIS[i] * parteInteira; reesultado.append(join("", nCopies(parteInteira, ROMANOS[i]))); } return resultado.toString(); } (...)
Com isso, implementamos totalmente o algoritmo apresentado anteriormente.
Importamos e utilizamos os métodos estáticos join
e nCopies
para facilitar o nosso trabalho. Segue o código completo:
import static java.util.Collections.nCopies; import static java.lang.String.join; public class NumerosRomanos { private static final int[] DECIMAIS = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; private static final String[] ROMANOS = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; public static String converterEmRomanos(int decimal) { StringBuilder resultado = new StringBuilder(); for (int i = 0; i < DECIMAIS.length; i++) { int parteInteira = decimal / DECIMAIS[i]; decimal -= DECIMAIS[i] * parteInteira; resultado.append(join("", nCopies(parteInteira, ROMANOS[i]))); } return resultado.toString(); } }
Implementação em PHP
Uma implementação em PHP semelhante à feita em Java segue abaixo.
Como arrays
em PHP são ordenados e têm uma inicialização muito mais elegante, podemos utilizá-los para representar nossa tabela de conversão satisfatoriamente.
<?php const ROMANOS = [ 1000 => "M", 900 => "CM", 500 => "D", 400 => "CD", 100 => "C", 90 => "XC", 50 => "L", 40 => "XL", 10 => "X", 9 => "IX", 5 => "V", 4 => "IV", 1 => "I" ]; function converterEmRomanos($decimal) { $resultado = ''; foreach (ROMANOS as $valor => $romano) { $div = intdiv($decimal, $valor); $resultado .= str_repeat($romano, $div); $decimal -= $div * $valor; } return $resultado; }
Implementação em Python
A implementação em Python segue a implementação em PHP.
A diferença é que em Python os dicionários não são ordenados, obrigando-nos a utilizar uma lista (uma tupla) de pares.
Um detalhe interessante é que, com a função divmod
, é possível obter a parte inteira da divisão e o resto ao mesmo tempo:
romanos = ( (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I") )def converterEmRomanos(decimal): resultado = '' for val, rom in romanos: div, decimal = divmod(decimal, val) resultado += rom * div return resultado
Conclusão
Como vimos, o algoritmo para converter decimais em romanos é bastante fácil de implementar. As implementações em Python e PHP podem não ter sido as mais idiomáticas, mas demonstram algumas diferenças em relação a Java. Por serem linguagens em que os tipos não são obrigatórios, observa-se que o código fica um pouco mais conciso.
Comentários