Автор оригинала: Fatos Morina.
1. Обзор
В этом уроке мы увидим, как мы можем преобразовать денежную сумму в словесное представление на Java.
Мы также увидим, как может выглядеть пользовательская реализация с помощью внешней библиотеки – Tradukisto .
2. Реализация
Давайте сначала начнем с нашей собственной реализации. Первым шагом является объявление двух Строковых массивов со следующими элементами:
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, то мы получим соответствующий элемент ones из массива на основе индекса:
if (n < 20) { return ones[(int) n]; }
Мы будем использовать аналогичный подход для чисел меньше 100, но теперь мы также должны использовать массив tens :
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+, которая может помочь нам преобразовать числа в их словесные представления. Во-первых, нам нужно импортировать его в наш проект (последнюю версию этой библиотеки можно найти здесь ):
pl.allegro.finance tradukisto 1.0.1
Теперь мы можем использовать Конвертеры денег s adwords() метод для этой конвертации:
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 .