Exibição de valores monetários em palavras
1. Visão geral
Neste tutorial, veremos como podemos converter uma quantia monetária em representação de palavras em Java.
Também veremos como uma implementação personalizada poderia ser, por meio de uma biblioteca externa -Tradukisto.
2. Implementação
Vamos primeiro começar com nossa própria implementação. The first step is to declare two String arrays com os seguintes elementos:
public static String[] ones = {
"", "one", "two", "three", "four",
"five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen",
"sixteen", "seventeen", "eighteen",
"nineteen"
};
public static String[] tens = {
"", // 0
"", // 1
"twenty", // 2
"thirty", // 3
"forty", // 4
"fifty", // 5
"sixty", // 6
"seventy", // 7
"eighty", // 8
"ninety" // 9
};
Quando recebermos uma entrada, precisaremos lidar com os valores inválidos (zero e valores negativos). Once a valid input is received, we can extract the number of dollars and cents into variables:
long dollars = (long) money;
long cents = Math.round((money - dollars) * 100);
Se o número fornecido for menor que 20, obteremos o elementoones' apropriado da matriz com base no índice:
if (n < 20) {
return ones[(int) n];
}
Usaremos uma abordagem semelhante para números menores que 100, mas agora temos que usar a matriztens também:
if (n < 100) {
return tens[(int) n / 10]
+ ((n % 10 != 0) ? " " : "")
+ ones[(int) n % 10];
}
Fazemos isso da mesma forma para números inferiores a mil.
Em seguida, usamos chamadas recursivas para lidar com números inferiores a um milhão, como mostrado abaixo:
if (n < 1_000_000) {
return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "")
+ convert(n % 1000);
}
A mesma abordagem é usada para números inferiores a um bilhão e assim por diante.
Aqui está o método principal que pode ser chamado para fazer essa conversão:
public static String getMoneyIntoWords(double money) {
long dollars = (long) money;
long cents = Math.round((money - dollars) * 100);
if (money == 0D) {
return "";
}
if (money < 0) {
return INVALID_INPUT_GIVEN;
}
String dollarsPart = "";
if (dollars > 0) {
dollarsPart = convert(dollars)
+ " dollar"
+ (dollars == 1 ? "" : "s");
}
String centsPart = "";
if (cents > 0) {
if (dollarParts.length() > 0) {
centsPart = " and ";
}
centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s");
}
return dollarsPart + centsPart;
}
Vamos testar nosso código para ter certeza de que funciona:
@Test
public void whenGivenDollarsAndCents_thenReturnWords() {
String expectedResult
= "nine hundred twenty four dollars and sixty cents";
assertEquals(
expectedResult,
NumberWordConverter.getMoneyIntoWords(924.6));
}
@Test
public void whenTwoBillionDollarsGiven_thenReturnWords() {
String expectedResult
= "two billion one hundred thirty three million two hundred"
+ " forty seven thousand eight hundred ten dollars";
assertEquals(
expectedResult,
NumberWordConverter.getMoneyIntoWords(2_133_247_810));
}
@Test
public void whenThirtyMillionDollarsGiven_thenReturnWords() {
String expectedResult
= "thirty three million three hundred forty eight thousand nine hundred seventy eight dollars";
assertEquals(
expectedResult,
NumberWordConverter.getMoneyIntoWords(33_348_978));
}
Vamos também testar alguns casos extremos e ter certeza de que os cobrimos também:
@Test
public void whenZeroDollarsGiven_thenReturnEmptyString() {
assertEquals("", NumberWordConverter.getMoneyIntoWords(0));
}
@Test
public void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() {
assertEquals(
"ninety six cents",
NumberWordConverter.getMoneyIntoWords(0.959));
}
@Test
public void whenNoDollarsAndOneCent_thenReturnCentSingular() {
assertEquals(
"one cent",
NumberWordConverter.getMoneyIntoWords(0.01));
}
3. Usando uma biblioteca
Agora que implementamos nosso próprio algoritmo, vamos fazer essa conversão usando uma biblioteca existente.
Tradukisto é uma biblioteca para Java 8+, que pode nos ajudar a converter números em suas representações de palavras. Primeiro, precisamos importá-lo para nosso projeto (a última versão desta biblioteca pode ser encontradahere):
pl.allegro.finance
tradukisto
1.0.1
Agora podemos usar o métodoMoneyConverters'sasWords() para fazer esta conversão:
public String getMoneyIntoWords(String input) {
MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE;
return converter.asWords(new BigDecimal(input));
}
Vamos testar esse método com um caso de teste simples:
@Test
public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() {
assertEquals(
"three hundred ten £ 00/100",
NumberWordConverter.getMoneyIntoWords("310"));
}
Também poderíamos usar a bibliotecaICU4J para fazer isso, mas ela é grande e vem com muitos outros recursos que estão fora do escopo deste artigo.
No entanto, verifique se é necessário suporte a Unicode e à globalização.
4. Conclusão
Neste artigo rápido, vimos duas abordagens sobre como fazer a conversão de uma soma de dinheiro em palavras.
O código para todos os exemplos explicados aqui e muito mais pode ser encontradoover on GitHub.