From e6d02cde636eb830be0b7d5d9bb5bd8aebed9c9d Mon Sep 17 00:00:00 2001 From: zwm <2076229520@qq.com> Date: Mon, 25 Aug 2025 18:30:31 +0800 Subject: [PATCH] Fix issue 4033 --- .../core/convert/NumberWordFormatter.java | 51 ++++++++++++------- .../core/convert/NumberWordFormatTest.java | 3 ++ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java index cc9e6a4bb4..b2536ea577 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberWordFormatter.java @@ -13,15 +13,18 @@ import cn.hutool.core.util.StrUtil; */ public class NumberWordFormatter { - private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", - "EIGHT", "NINE"}; - private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", - "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"}; - private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY", - "SEVENTY", "EIGHTY", "NINETY"}; - private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION", "TRILLION"}; + private static final String[] NUMBER = new String[] { "", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", + "EIGHT", "NINE" }; + private static final String[] NUMBER_TEEN = new String[] { "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", + "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN" }; + private static final String[] NUMBER_TEN = new String[] { "TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY", + "SEVENTY", "EIGHTY", "NINETY" }; + private static final String[] NUMBER_MORE = new String[] { "", "THOUSAND", "MILLION", "BILLION", "TRILLION" }; - private static final String[] NUMBER_SUFFIX = new String[]{"k", "w", "", "m", "", "", "b", "", "", "t", "", "", "p", "", "", "e"}; + private static final String[] NUMBER_SUFFIX = new String[] { "k", "w", "m", "b", "t", "p", "e" }; + + // 标准单位序列(k, m, b, t, p, e)在NUMBER_SUFFIX中的索引 + private static final int[] STANDARD_UNIT_INDICES = { 0, 2, 3, 4, 5, 6 }; /** * 将阿拉伯数字转为英文表达式 @@ -61,18 +64,32 @@ public class NumberWordFormatter { if (value < 1000) { return String.valueOf(value); } - int index = -1; + double res = value; - while (res > 10 && (false == isTwo || index < 1)) { - if (res >= 1000) { + int index = 0; + + if (isTwo) { + // 当isTwo为true时,只使用k和w单位 + if (value >= 100000) { + // 使用w单位(除以10000,即10k = 1w) + res = value / 10000.0; + index = 1; // w在NUMBER_SUFFIX[1] + } else { + // 使用k单位(除以1000) + res = value / 1000.0; + index = 0; // k在NUMBER_SUFFIX[0] + } + } else { + // 当isTwo为false时,使用标准单位序列 (k, m, b, t, p, e) + // 对应NUMBER_SUFFIX中的索引为 0, 2, 3, 4, 5, 6 + int unitIndex = -1; + while (res >= 1000 && unitIndex < STANDARD_UNIT_INDICES.length - 1) { res = res / 1000; - index++; - } - if (res > 10) { - res = res / 10; - index++; + unitIndex++; } + index = STANDARD_UNIT_INDICES[unitIndex]; } + return String.format("%s%s", NumberUtil.decimalFormat("#.##", res), NUMBER_SUFFIX[index]); } @@ -107,7 +124,7 @@ public class NumberWordFormatter { StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分 for (int i = 0; i < lstrrev.length() / 3; i++) { a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位 - if (false == "000".equals(a[i])) { // 用来避免这种情况:1000000 = one million + if (!"000".equals(a[i])) { // 用来避免这种情况:1000000 = one million // thousand only if (i != 0) { lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加: diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java index feb93efce7..4c563b56a3 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberWordFormatTest.java @@ -33,6 +33,9 @@ public class NumberWordFormatTest { final String format5 = NumberWordFormatter.formatSimple(438); assertEquals("438", format5); + + final String format6 = NumberWordFormatter.formatSimple(1000000, false); + assertEquals("1m", format6); } @Test