Displaying Money Amounts in Words – 用文字显示货币数量

最后修改: 2018年 3月 21日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll see how we can convert a monetary amount into words-representation in Java.

在本教程中,我们将看到如何在Java中把一个货币金额转换为文字表述。

We’ll also see how a custom implementation could look like, via an external library – Tradukisto.

我们还将看到,通过一个外部库–Tradukisto,一个自定义的实现会是什么样子。

2. Implementation

2.实施

Let’s first start with our own implementation. The first step is to declare two String arrays with the following elements:

让我们首先从我们自己的实现开始。第一步是声明两个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
};

When we receive an input, we’ll need to handle the invalid values (zero and negative values). 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);

If the number given is less than 20, then we’ll get the appropriate ones’ element from the array based on the index:

如果给出的数字小于20,那么我们将根据索引从数组中获得适当的ones’元素。

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

We’ll use a similar approach for numbers less than 100, but now we have to use tens array as well:

我们将对小于100的数字使用类似的方法,但现在我们也必须使用tens array。

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

We do this similarly for numbers that are less than one thousand.

对于小于一千的数字,我们也是这样做的。

Next, we use recursive calls to deal with numbers that are less than one million, as shown below:

接下来,我们使用递归调用来处理小于一百万的数字,如下所示。

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

The same approach is used for numbers that are less than one billion, and so on.

同样的方法也用于小于10亿的数字,以此类推。

Here is the main method that can be called to do this conversion:

这里是可以被调用来进行这种转换的主要方法。

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

Let’s test our code to make sure it works:

让我们测试一下我们的代码,以确保它能工作。

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

Let’s also test some edge cases, and make sure we have covered them as well:

让我们也测试一些边缘案例,并确保我们也已经涵盖了这些案例。

@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. Using a Library

3.使用一个库

Now that we’ve implemented our own algorithm, let’s do this conversion by using an existing library.

现在我们已经实现了自己的算法,让我们通过使用一个现有的库来进行这种转换。

Tradukisto is a library for Java 8+, which can help us convert numbers to their word representations. First, we need to import it into our project (the latest version of this library can be found here):

Tradukisto是一个适用于Java 8+的库,它可以帮助我们将数字转换为其文字表示。首先,我们需要将其导入我们的项目中(该库的最新版本可以在这里)。

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

We can now use MoneyConverters‘s asWords() method to do this conversion:

我们现在可以使用MoneyConvertersasWords()方法来做这个转换。

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

Let’s test this method with a simple test case:

让我们用一个简单的测试案例来测试这个方法。

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

We could also use the ICU4J library to do this, but it’s a large one and comes with many other features that are out of the scope of this article.

我们也可以使用ICU4J库来做到这一点,但它是一个很大的库,并且带有许多其他功能,不在本文的范围之内。

However, have a look at it if Unicode and globalization support is needed.

然而,如果需要Unicode和全球化支持,请看一下它。

4. Conclusion

4.结论

In this quick article, we saw two approaches on how to do the conversion of a sum of money into words.

在这篇快速文章中,我们看到了两种关于如何将一笔钱转换为文字的方法。

The code for all the examples explained here, and much more can be found over on GitHub.

这里解释的所有例子的代码,以及更多的代码可以在GitHub上找到