diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/convert/Convert.java b/hutool-core/src/main/java/org/dromara/hutool/core/convert/Convert.java
index fa63e7419..3ffdf95ef 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/convert/Convert.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/convert/Convert.java
@@ -19,6 +19,8 @@ import org.dromara.hutool.core.convert.impl.CollectionConverter;
import org.dromara.hutool.core.convert.impl.EnumConverter;
import org.dromara.hutool.core.convert.impl.MapConverter;
import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.core.math.NumberChineseFormatter;
+import org.dromara.hutool.core.math.NumberWordFormatter;
import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.UnicodeUtil;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/convert/impl/NumberConverter.java b/hutool-core/src/main/java/org/dromara/hutool/core/convert/impl/NumberConverter.java
index 43c789e87..9d75ce477 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/convert/impl/NumberConverter.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/convert/impl/NumberConverter.java
@@ -66,7 +66,11 @@ public class NumberConverter extends AbstractConverter {
@Override
protected String convertToStr(final Object value) {
final String result = StrUtil.trim(super.convertToStr(value));
- if (null != result && result.length() > 1) {
+ if(StrUtil.isEmpty(result)){
+ throw new ConvertException("Can not convert empty value to Number!");
+ }
+
+ if (result.length() > 1) {
// 非单个字符才判断末尾的标识符
final char c = Character.toUpperCase(result.charAt(result.length() - 1));
if (c == 'D' || c == 'L' || c == 'F') {
@@ -75,9 +79,6 @@ public class NumberConverter extends AbstractConverter {
}
}
- if(StrUtil.isEmpty(result)){
- throw new ConvertException("Can not convert empty value to Number!");
- }
return result;
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/CalendarUtil.java
index 6578240da..95cb13b40 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/date/CalendarUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/CalendarUtil.java
@@ -13,7 +13,7 @@
package org.dromara.hutool.core.date;
import org.dromara.hutool.core.comparator.CompareUtil;
-import org.dromara.hutool.core.convert.NumberChineseFormatter;
+import org.dromara.hutool.core.math.NumberChineseFormatter;
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
import org.dromara.hutool.core.date.format.parser.DateParser;
import org.dromara.hutool.core.date.format.parser.FastDateParser;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/chinese/ChineseDate.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/chinese/ChineseDate.java
index edac9a43a..0a0973f96 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/date/chinese/ChineseDate.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/chinese/ChineseDate.java
@@ -12,7 +12,7 @@
package org.dromara.hutool.core.date.chinese;
-import org.dromara.hutool.core.convert.NumberChineseFormatter;
+import org.dromara.hutool.core.math.NumberChineseFormatter;
import org.dromara.hutool.core.date.CalendarUtil;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberChineseFormatter.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberChineseFormatter.java
similarity index 99%
rename from hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberChineseFormatter.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/math/NumberChineseFormatter.java
index 486e668f9..f0808428b 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberChineseFormatter.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberChineseFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Copyright (c) 2023-2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
@@ -10,10 +10,9 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.convert;
+package org.dromara.hutool.core.math;
import org.dromara.hutool.core.lang.Assert;
-import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.array.ArrayUtil;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberRomanFormatter.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberRomanFormatter.java
new file mode 100644
index 000000000..1816ce133
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberRomanFormatter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024. looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.math;
+
+import org.dromara.hutool.core.text.StrUtil;
+
+/**
+ * 数字和罗马数字转换
+ *
+ * @author dazer
+ * @since 6.0.0
+ */
+public class NumberRomanFormatter {
+
+ /**
+ * 整数转罗马数字
+ * 限制:[1,3999]的正整数
+ *
+ * - I 1
+ * - V 5
+ * - X 10
+ * - L 50
+ * - C 100
+ * - D 500
+ * - M 1000
+ *
+ *
+ * @param num [1,3999]的正整数
+ * @return 罗马数字
+ * @author dazer
+ * @since 6.0.0
+ */
+ public static String intToRoman(final int num) {
+ if (num > 3999 || num < 1) {
+ return StrUtil.EMPTY;
+ }
+ final String[] thousands = {"", "M", "MM", "MMM"};
+ final String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
+ final String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
+ final String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
+
+ return thousands[num / 1000] +
+ hundreds[(num % 1000) / 100] +
+ tens[(num % 100) / 10] +
+ ones[num % 10];
+ }
+
+ /**
+ * 罗马数字转整数
+ *
+ * @param roman 罗马字符
+ * @return 整数
+ * @throws IllegalArgumentException 如果传入非罗马字符串,抛出异常
+ * @author dazer
+ * @since 6.0.0
+ */
+ public static int romanToInt(final String roman) {
+ int result = 0;
+ int prevValue = 0;
+ int currValue;
+
+ for (int i = roman.length() - 1; i >= 0; i--) {
+ final char c = roman.charAt(i);
+ switch (c) {
+ case 'I':
+ currValue = 1;
+ break;
+ case 'V':
+ currValue = 5;
+ break;
+ case 'X':
+ currValue = 10;
+ break;
+ case 'L':
+ currValue = 50;
+ break;
+ case 'C':
+ currValue = 100;
+ break;
+ case 'D':
+ currValue = 500;
+ break;
+ case 'M':
+ currValue = 1000;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid Roman character: " + c);
+ }
+ if (currValue < prevValue) {
+ result -= currValue;
+ } else {
+ result += currValue;
+ }
+
+ prevValue = currValue;
+ }
+ return result;
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java
index 02e69f8ab..34afa41cf 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java
@@ -903,16 +903,16 @@ public class NumberUtil extends NumberValidator {
/**
* 数字转{@link BigDecimal}
- * null或""或"NaN"或空白符转换为0
+ * null或""或空白符抛出{@link IllegalArgumentException}异常
+ * "NaN"转为{@link BigDecimal#ZERO}
*
* @param numberStr 数字字符串
* @return {@link BigDecimal}
- * @since 4.0.9
+ * @throws IllegalArgumentException null或""或"NaN"或空白符抛出此异常
*/
- public static BigDecimal toBigDecimal(final String numberStr) {
- if (StrUtil.isBlank(numberStr)) {
- return BigDecimal.ZERO;
- }
+ public static BigDecimal toBigDecimal(final String numberStr) throws IllegalArgumentException{
+ // 统一规则,不再转换带有歧义的null、""和空格
+ Assert.notBlank(numberStr, "Number str must be not blank!");
// issue#3241,优先调用构造解析
try{
@@ -934,9 +934,8 @@ public class NumberUtil extends NumberValidator {
* @since 5.4.5
*/
public static BigInteger toBigInteger(final Number number) {
- if (null == number) {
- return BigInteger.ZERO;
- }
+ // 统一规则,不再转换带有歧义的null
+ Assert.notNull(number, "Number must be not null!");
if (number instanceof BigInteger) {
return (BigInteger) number;
@@ -951,12 +950,21 @@ public class NumberUtil extends NumberValidator {
* 数字转{@link BigInteger}
* null或""或空白符转换为0
*
- * @param number 数字字符串
+ * @param numberStr 数字字符串
* @return {@link BigInteger}
* @since 5.4.5
*/
- public static BigInteger toBigInteger(final String number) {
- return StrUtil.isBlank(number) ? BigInteger.ZERO : new BigInteger(number);
+ public static BigInteger toBigInteger(final String numberStr) {
+ // 统一规则,不再转换带有歧义的null、""和空格
+ Assert.notBlank(numberStr, "Number str must be not blank!");
+
+ try{
+ return new BigInteger(numberStr);
+ } catch (final Exception ignore){
+ // 忽略解析错误
+ }
+
+ return parseBigInteger(numberStr);
}
/**
@@ -1057,7 +1065,7 @@ public class NumberUtil extends NumberValidator {
* @return 0或非0值
*/
public static BigInteger nullToZero(final BigInteger number) {
- return number == null ? BigInteger.ZERO : number;
+ return ObjUtil.defaultIfNull(number, BigInteger.ZERO);
}
/**
@@ -1574,18 +1582,7 @@ public class NumberUtil extends NumberValidator {
* @author dazer
*/
public static String intToRoman(final int num) {
- if (num > 3999 || num < 1 ){
- return StrUtil.EMPTY;
- }
- final String[] thousands = {"", "M", "MM", "MMM"};
- final String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
- final String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
- final String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
-
- return thousands[num / 1000] +
- hundreds[(num % 1000) / 100] +
- tens[(num % 100) / 10] +
- ones[num % 10];
+ return NumberRomanFormatter.intToRoman(num);
}
/**
@@ -1597,45 +1594,6 @@ public class NumberUtil extends NumberValidator {
* @author dazer
*/
public static int romanToInt(final String roman) {
- int result = 0;
- int prevValue = 0;
- int currValue;
-
- for (int i = roman.length() - 1; i >= 0; i--) {
- final char c = roman.charAt(i);
- switch (c) {
- case 'I':
- currValue = 1;
- break;
- case 'V':
- currValue = 5;
- break;
- case 'X':
- currValue = 10;
- break;
- case 'L':
- currValue = 50;
- break;
- case 'C':
- currValue = 100;
- break;
- case 'D':
- currValue = 500;
- break;
- case 'M':
- currValue = 1000;
- break;
- default:
- throw new IllegalArgumentException("Invalid Roman character: " + c);
- }
- if (currValue< prevValue) {
- result -= currValue;
- } else {
- result += currValue;
- }
-
- prevValue = currValue;
- }
- return result;
+ return NumberRomanFormatter.romanToInt(roman);
}
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberWordFormatter.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberWordFormatter.java
similarity index 98%
rename from hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberWordFormatter.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/math/NumberWordFormatter.java
index 594654b15..76e367d9e 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/convert/NumberWordFormatter.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberWordFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Copyright (c) 2023-2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
@@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.convert;
+package org.dromara.hutool.core.math;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.StrUtil;
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberChineseFormatterTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberChineseFormatterTest.java
similarity index 99%
rename from hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberChineseFormatterTest.java
rename to hutool-core/src/test/java/org/dromara/hutool/core/math/NumberChineseFormatterTest.java
index 894b489d6..73f2228ff 100644
--- a/hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberChineseFormatterTest.java
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberChineseFormatterTest.java
@@ -10,8 +10,9 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.convert;
+package org.dromara.hutool.core.math;
+import org.dromara.hutool.core.convert.Convert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberUtilTest.java
index 94c51b521..d3cf00464 100644
--- a/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberUtilTest.java
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberUtilTest.java
@@ -13,7 +13,6 @@
package org.dromara.hutool.core.math;
import org.dromara.hutool.core.lang.Console;
-import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -380,6 +379,18 @@ public class NumberUtilTest {
Assertions.assertEquals(new BigDecimal("9.0E+7"), NumberUtil.toBigDecimal("9.0E+7"));
}
+ @Test
+ void emptyToBigDecimalTest(){
+ Assertions.assertThrows(IllegalArgumentException.class,()->{
+ NumberUtil.toBigDecimal("");
+ });
+ }
+
+ @Test
+ void naNToBigDecimalTest(){
+ Assertions.assertEquals(BigDecimal.ZERO, NumberUtil.toBigDecimal("NaN"));
+ }
+
@Test
public void issue2878Test() throws ParseException {
// https://github.com/dromara/hutool/issues/2878
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberWordFormatTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberWordFormatTest.java
similarity index 95%
rename from hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberWordFormatTest.java
rename to hutool-core/src/test/java/org/dromara/hutool/core/math/NumberWordFormatTest.java
index 369df6dd7..c67ff70a0 100644
--- a/hutool-core/src/test/java/org/dromara/hutool/core/convert/NumberWordFormatTest.java
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/math/NumberWordFormatTest.java
@@ -10,8 +10,9 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.convert;
+package org.dromara.hutool.core.math;
+import org.dromara.hutool.core.math.NumberWordFormatter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;