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]的正整数 + * + * + * @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;