Перейти к основному содержимому

Отображение денежных сумм в словах

· 4 мин. чтения

1. Обзор

В этом уроке мы увидим, как мы можем преобразовать денежную сумму в словесное представление в Java.

Мы также посмотрим, как может выглядеть пользовательская реализация через внешнюю библиотеку — Tradukisto .

2. Реализация

Давайте сначала начнем с нашей собственной реализации. Первый шаг — объявить два массива String со следующими элементами:

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
};

Когда мы получим ввод, нам нужно будет обработать недопустимые значения (нулевые и отрицательные значения). После получения действительного ввода мы можем извлечь количество долларов и центов в переменные:

long dollars = (long) money;
long cents = Math.round((money - dollars) * 100);

Если заданное число меньше 20, то мы получим соответствующий элемент из массива на основе индекса:

if (n < 20) {
return ones[(int) n];
}

Мы будем использовать аналогичный подход для чисел меньше 100, но теперь мы также должны использовать массив десятков :

if (n < 100) {
return tens[(int) n / 10]
+ ((n % 10 != 0) ? " " : "")
+ ones[(int) n % 10];
}

Мы делаем это аналогичным образом для чисел, которые меньше одной тысячи.

Затем мы используем рекурсивные вызовы для работы с числами меньше миллиона, как показано ниже:

if (n < 1_000_000) {
return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "")
+ convert(n % 1000);
}

Тот же подход используется для чисел меньше одного миллиарда и так далее.

Вот основной метод, который можно вызвать для этого преобразования:

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;
}

Давайте протестируем наш код, чтобы убедиться, что он работает:

@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));
}

Давайте также проверим некоторые крайние случаи и убедимся, что мы их тоже рассмотрели:

@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. Использование библиотеки

Теперь, когда мы реализовали собственный алгоритм, давайте сделаем это преобразование, используя существующую библиотеку.

Tradukisto — это библиотека для Java 8+, которая может помочь нам преобразовать числа в их словесные представления. Во-первых, нам нужно импортировать ее в наш проект (последнюю версию этой библиотеки можно найти здесь ):

<dependency>
<groupId>pl.allegro.finance</groupId>
<artifactId>tradukisto</artifactId>
<version>1.0.1</version>
</dependency>

Теперь мы можем использовать метод asWords () класса MoneyConverters для выполнения этого преобразования:

public String getMoneyIntoWords(String input) {
MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE;
return converter.asWords(new BigDecimal(input));
}

Давайте проверим этот метод на простом тестовом примере:

@Test
public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() {
assertEquals(
"three hundred ten £ 00/100",
NumberWordConverter.getMoneyIntoWords("310"));
}

Мы также могли бы использовать для этого библиотеку ICU4J , но она большая и имеет множество других функций, которые выходят за рамки этой статьи.

Однако взгляните на него, если нужна поддержка Unicode и глобализации.

4. Вывод

В этой быстрой статье мы увидели два подхода к преобразованию денежной суммы в слова.

Код для всех описанных здесь примеров и многое другое можно найти на GitHub .