1. 概述
本教程将介绍如何在 Java 中将货币金额转换为英文单词表示。我们将通过两种方式实现:
- ✅ 自定义实现(从零开始构建转换逻辑)
- ✅ 使用第三方库(Tradukisto)
面向有经验的开发者,基础概念将简明扼要,重点展示核心实现和踩坑点。
2. 自定义实现
2.1 核心数据结构
第一步是定义两个基础字符串数组,用于存储数字单词表示:
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
"sixy", // 6
"seventy", // 7
"eighty", // 8
"ninety" // 9
};
2.2 输入处理与拆分
接收到输入后,需处理非法值(零或负数)。有效输入需拆分为美元和美分:
long dollars = (long) money;
long cents = Math.round((money - dollars) * 100);
2.3 分段转换逻辑
根据数字范围采用不同处理策略:
小于20的数字:直接从
ones
数组获取if (n < 20) { return ones[(int) n]; }
小于100的数字:组合
tens
和ones
数组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); }
2.4 主转换方法
核心转换逻辑整合:
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 (dollarsPart.length() > 0) {
centsPart = " and ";
}
centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s");
}
return dollarsPart + centsPart;
}
2.5 测试用例验证
常规金额测试:
@Test
void whenGivenDollarsAndCents_thenReturnWords() {
String expectedResult = "nine hundred twenty four dollars and sixty cents";
assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(924.6));
}
@Test
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
void whenZeroDollarsGiven_thenReturnEmptyString() {
assertEquals("", NumberWordConverter.getMoneyIntoWords(0));
}
@Test
void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() {
assertEquals("ninety six cents", NumberWordConverter.getMoneyIntoWords(0.959));
}
@Test
void whenNoDollarsAndOneCent_thenReturnCentSingular() {
assertEquals("one cent", NumberWordConverter.getMoneyIntoWords(0.01));
}
⚠️ 踩坑提示:
- 美分四舍五入需用
Math.round()
而非强制转换 - 单复数处理(dollar/dollars, cent/cents)需严格判断
3. 使用第三方库
3.1 引入 Tradukisto 库
Tradukisto 是专门用于数字转单词的 Java 库。Maven 依赖:
<dependency>
<groupId>pl.allegro.finance</groupId>
<artifactId>tradukisto</artifactId>
<version>1.0.1</version>
</dependency>
3.2 简单粗暴的实现
使用 MoneyConverters
一行搞定转换:
public String getMoneyIntoWords(String input) {
MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE;
return converter.asWords(new BigDecimal(input));
}
3.3 库使用测试
@Test
void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() {
assertEquals("three hundred ten £ 00/100",
NumberWordConverter.getMoneyIntoWords("310"));
}
✅ 优势:
- 零维护成本
- 内置多语言支持
❌ 局限:
- 输出格式固定(如
£ 00/100
后缀) - 不支持自定义货币单位
4. 总结
两种方案对比:
方案 | 适用场景 | 维护成本 | 定制灵活性 |
---|---|---|---|
自定义实现 | 特殊格式需求/无依赖环境 | 高 | ⭐⭐⭐⭐⭐ |
Tradukisto | 快速实现/标准化输出 | 低 | ⭐⭐ |
决策建议:
- 生产环境优先选择库方案(简单可靠)
- 特殊格式需求(如中文金额)需自定义实现
完整代码示例见 GitHub 项目。