From 084870261fcef89b4a26151664a381d61667b065 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 7 Jun 2022 13:58:24 +0800 Subject: [PATCH] del methdos --- .../hutool/core/comparator/CompareUtil.java | 80 +++ .../hutool/core/lang/mutable/MutableByte.java | 4 +- .../core/lang/mutable/MutableDouble.java | 4 +- .../core/lang/mutable/MutableFloat.java | 12 +- .../hutool/core/lang/mutable/MutableInt.java | 4 +- .../hutool/core/lang/mutable/MutableLong.java | 4 +- .../core/lang/mutable/MutableShort.java | 12 +- .../java/cn/hutool/core/math/Arrangement.java | 6 +- .../java/cn/hutool/core/math/Combination.java | 10 +- .../java/cn/hutool/core/math/MathUtil.java | 199 +++++++ .../java/cn/hutool/core/math/NumberUtil.java | 541 ++---------------- .../hutool/core/util/PrimitiveArrayUtil.java | 57 -- .../java/cn/hutool/core/util/RandomUtil.java | 2 +- .../core/collection/PartitionIterTest.java | 4 +- .../cn/hutool/core/math/MathUtilTest.java | 44 ++ .../cn/hutool/core/util/ArrayUtilTest.java | 21 - .../cn/hutool/core/util/NumberUtilTest.java | 70 +-- 17 files changed, 425 insertions(+), 649 deletions(-) create mode 100644 hutool-core/src/test/java/cn/hutool/core/math/MathUtilTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java b/hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java index 520a9a4bf..945045668 100644 --- a/hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/comparator/CompareUtil.java @@ -11,6 +11,86 @@ import java.util.function.Function; */ public class CompareUtil { + // ------------------------------------------------------------------------------------------- compare + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 + * @see Character#compare(char, char) + * @since 3.0.1 + */ + public static int compare(final char x, final char y) { + return Character.compare(x, y); + } + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 + * @see Double#compare(double, double) + * @since 3.0.1 + */ + public static int compare(final double x, final double y) { + return Double.compare(x, y); + } + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 + * @see Integer#compare(int, int) + * @since 3.0.1 + */ + public static int compare(final int x, final int y) { + return Integer.compare(x, y); + } + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 + * @see Long#compare(long, long) + * @since 3.0.1 + */ + public static int compare(final long x, final long y) { + return Long.compare(x, y); + } + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 + * @see Short#compare(short, short) + * @since 3.0.1 + */ + public static int compare(final short x, final short y) { + return Short.compare(x, y); + } + + /** + * 比较两个值的大小 + * + * @param x 第一个值 + * @param y 第二个值 + * @return x==y返回0,x<y返回-1,x>y返回1 + * @see Byte#compare(byte, byte) + * @since 3.0.1 + */ + public static int compare(final byte x, final byte y) { + return Byte.compare(x, y); + } + /** * 获取自然排序器,即默认排序器 * diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableByte.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableByte.java index 5cb493511..e0f05026d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableByte.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableByte.java @@ -1,6 +1,6 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** * 可变 {@code byte} 类型 @@ -186,7 +186,7 @@ public class MutableByte extends Number implements Comparable, Muta */ @Override public int compareTo(final MutableByte other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java index f3732a4d1..e068f7212 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableDouble.java @@ -1,6 +1,6 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** * 可变 {@code double} 类型 @@ -180,7 +180,7 @@ public class MutableDouble extends Number implements Comparable, */ @Override public int compareTo(final MutableDouble other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableFloat.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableFloat.java index 84572f191..345bff4e7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableFloat.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableFloat.java @@ -1,9 +1,9 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** - * 可变 float 类型 + * 可变 {@code float} 类型 * * @see Float * @since 3.0.1 @@ -152,12 +152,12 @@ public class MutableFloat extends Number implements Comparable, Mu * 相等需同时满足如下条件: *
    *
  1. 非空
  2. - *
  3. 类型为 {@link MutableFloat}
  4. + *
  5. 类型为 {@code MutableFloat}
  6. *
  7. 值相等
  8. *
* * @param obj 比对的对象 - * @return 相同返回true,否则 false + * @return 相同返回true,否则 {@code false} */ @Override public boolean equals(final Object obj) { @@ -176,12 +176,12 @@ public class MutableFloat extends Number implements Comparable, Mu /** * 比较 * - * @param other 其它 {@link MutableFloat} 对象 + * @param other 其它 {@code MutableFloat} 对象 * @return x==y返回0,x<y返回-1,x>y返回1 */ @Override public int compareTo(final MutableFloat other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java index 1b2c64611..912a67afc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableInt.java @@ -1,6 +1,6 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** * 可变 int 类型 @@ -181,7 +181,7 @@ public class MutableInt extends Number implements Comparable, Mutabl */ @Override public int compareTo(final MutableInt other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableLong.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableLong.java index cafdca29f..4f1d08ac1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableLong.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableLong.java @@ -1,6 +1,6 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** * 可变 {@code long} 类型 @@ -193,7 +193,7 @@ public class MutableLong extends Number implements Comparable, Muta */ @Override public int compareTo(final MutableLong other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableShort.java b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableShort.java index 654d6d214..0e53d907e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableShort.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/mutable/MutableShort.java @@ -1,9 +1,9 @@ package cn.hutool.core.lang.mutable; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.comparator.CompareUtil; /** - * 可变 short 类型 + * 可变 {@code short} 类型 * * @see Short * @since 3.0.1 @@ -157,12 +157,12 @@ public class MutableShort extends Number implements Comparable, Mu * 相等需同时满足如下条件: *
    *
  1. 非空
  2. - *
  3. 类型为 {@link MutableShort}
  4. + *
  5. 类型为 {@code MutableShort}
  6. *
  7. 值相等
  8. *
* * @param obj 比对的对象 - * @return 相同返回true,否则 false + * @return 相同返回true,否则 {@code false} */ @Override public boolean equals(final Object obj) { @@ -181,12 +181,12 @@ public class MutableShort extends Number implements Comparable, Mu /** * 比较 * - * @param other 其它 {@link MutableShort} 对象 + * @param other 其它 {@code MutableShort} 对象 * @return x==y返回0,x<y返回-1,x>y返回1 */ @Override public int compareTo(final MutableShort other) { - return NumberUtil.compare(this.value, other.value); + return CompareUtil.compare(this.value, other.value); } // ----------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/math/Arrangement.java b/hutool-core/src/main/java/cn/hutool/core/math/Arrangement.java index ab9bbfc79..1a51c8634 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/Arrangement.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/Arrangement.java @@ -9,7 +9,7 @@ import java.util.List; /** * 排列A(n, m)
- * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 + * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 * * @author looly * @since 4.0.7 @@ -47,9 +47,9 @@ public class Arrangement implements Serializable { */ public static long count(final int n, final int m) { if (n == m) { - return NumberUtil.factorial(n); + return MathUtil.factorial(n); } - return (n > m) ? NumberUtil.factorial(n, n - m) : 0; + return (n > m) ? MathUtil.factorial(n, n - m) : 0; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/math/Combination.java b/hutool-core/src/main/java/cn/hutool/core/math/Combination.java index 7fd55f5a8..821522a3f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/Combination.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/Combination.java @@ -1,15 +1,15 @@ package cn.hutool.core.math; +import cn.hutool.core.text.StrUtil; + import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import cn.hutool.core.text.StrUtil; - /** * 组合,即C(n, m)
- * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 + * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 * * @author looly * @since 4.0.6 @@ -21,7 +21,7 @@ public class Combination implements Serializable { /** * 组合,即C(n, m)
- * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 + * 排列组合相关类 参考:http://cgs1999.iteye.com/blog/2327664 * * @param datas 用于组合的数据 */ @@ -40,7 +40,7 @@ public class Combination implements Serializable { if (0 == m || n == m) { return 1; } - return (n > m) ? NumberUtil.factorial(n, n - m) / NumberUtil.factorial(m) : 0; + return (n > m) ? MathUtil.factorial(n, n - m) / MathUtil.factorial(m) : 0; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/math/MathUtil.java b/hutool-core/src/main/java/cn/hutool/core/math/MathUtil.java index 41a4665c3..0a2bffbb8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/MathUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/MathUtil.java @@ -1,5 +1,9 @@ package cn.hutool.core.math; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.text.StrUtil; + +import java.math.BigInteger; import java.util.List; /** @@ -11,6 +15,14 @@ import java.util.List; */ public class MathUtil { + /** + * 0-20对应的阶乘,超过20的阶乘会超过Long.MAX_VALUE + */ + private static final long[] FACTORIALS = new long[]{ + 1L, 1L, 2L, 6L, 24L, 120L, 720L, 5040L, 40320L, 362880L, 3628800L, 39916800L, 479001600L, 6227020800L, + 87178291200L, 1307674368000L, 20922789888000L, 355687428096000L, 6402373705728000L, 121645100408832000L, + 2432902008176640000L}; + //--------------------------------------------------------------------------------------------- Arrangement /** * 计算排列数,即A(n, m) = n!/(n-m)! @@ -100,4 +112,191 @@ public class MathUtil { final int centPart = (int) (cent % 100); return new Money(yuan, centPart).getAmount().doubleValue(); } + + /** + * 计算阶乘 + *

+ * n! = n * (n-1) * ... * 2 * 1 + *

+ * + * @param n 阶乘起始 + * @return 结果 + * @since 5.6.0 + */ + public static BigInteger factorial(final BigInteger n) { + if (n.equals(BigInteger.ZERO)) { + return BigInteger.ONE; + } + return factorial(n, BigInteger.ZERO); + } + + /** + * 计算范围阶乘 + *

+ * factorial(start, end) = start * (start - 1) * ... * (end + 1) + *

+ * + * @param start 阶乘起始(包含) + * @param end 阶乘结束,必须小于起始(不包括) + * @return 结果 + * @since 5.6.0 + */ + public static BigInteger factorial(BigInteger start, BigInteger end) { + Assert.notNull(start, "Factorial start must be not null!"); + Assert.notNull(end, "Factorial end must be not null!"); + if (start.compareTo(BigInteger.ZERO) < 0 || end.compareTo(BigInteger.ZERO) < 0) { + throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be > 0, but got start={}, end={}", start, end)); + } + + if (start.equals(BigInteger.ZERO)) { + start = BigInteger.ONE; + } + + if (end.compareTo(BigInteger.ONE) < 0) { + end = BigInteger.ONE; + } + + BigInteger result = start; + end = end.add(BigInteger.ONE); + while (start.compareTo(end) > 0) { + start = start.subtract(BigInteger.ONE); + result = result.multiply(start); + } + return result; + } + + /** + * 计算范围阶乘 + *

+ * factorial(start, end) = start * (start - 1) * ... * (end + 1) + *

+ * + * @param start 阶乘起始(包含) + * @param end 阶乘结束,必须小于起始(不包括) + * @return 结果 + * @since 4.1.0 + */ + public static long factorial(final long start, final long end) { + // 负数没有阶乘 + if (start < 0 || end < 0) { + throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be >= 0, but got start={}, end={}", start, end)); + } + if (0L == start || start == end) { + return 1L; + } + if (start < end) { + return 0L; + } + return factorialMultiplyAndCheck(start, factorial(start - 1, end)); + } + + /** + * 计算范围阶乘中校验中间的计算是否存在溢出,factorial提前做了负数和0的校验,因此这里没有校验数字的正负 + * + * @param a 乘数 + * @param b 被乘数 + * @return 如果 a * b的结果没有溢出直接返回,否则抛出异常 + */ + private static long factorialMultiplyAndCheck(final long a, final long b) { + if (a <= Long.MAX_VALUE / b) { + return a * b; + } + throw new IllegalArgumentException(StrUtil.format("Overflow in multiplication: {} * {}", a, b)); + } + + /** + * 计算阶乘 + *

+ * n! = n * (n-1) * ... * 2 * 1 + *

+ * + * @param n 阶乘起始 + * @return 结果 + */ + public static long factorial(final long n) { + if (n < 0 || n > 20) { + throw new IllegalArgumentException(StrUtil.format("Factorial must have n >= 0 and n <= 20 for n!, but got n = {}", n)); + } + return FACTORIALS[(int) n]; + } + + /** + * 平方根算法
+ * 推荐使用 {@link Math#sqrt(double)} + * + * @param x 值 + * @return 平方根 + */ + public static long sqrt(long x) { + long y = 0; + long b = (~Long.MAX_VALUE) >>> 1; + while (b > 0) { + if (x >= y + b) { + x -= y + b; + y >>= 1; + y += b; + } else { + y >>= 1; + } + b >>= 2; + } + return y; + } + + /** + * 可以用于计算双色球、大乐透注数的方法
+ * 比如大乐透35选5可以这样调用processMultiple(7,5); 就是数学中的:C75=7*6/2*1 + * + * @param selectNum 选中小球个数 + * @param minNum 最少要选中多少个小球 + * @return 注数 + */ + public static int processMultiple(final int selectNum, final int minNum) { + final int result; + result = mathSubNode(selectNum, minNum) / mathNode(selectNum - minNum); + return result; + } + + /** + * 最大公约数 + * + * @param m 第一个值 + * @param n 第二个值 + * @return 最大公约数 + */ + public static int divisor(int m, int n) { + while (m % n != 0) { + final int temp = m % n; + m = n; + n = temp; + } + return n; + } + + /** + * 最小公倍数 + * + * @param m 第一个值 + * @param n 第二个值 + * @return 最小公倍数 + */ + public static int multiple(final int m, final int n) { + return m * n / divisor(m, n); + } + + private static int mathSubNode(final int selectNum, final int minNum) { + if (selectNum == minNum) { + return 1; + } else { + return selectNum * mathSubNode(selectNum - 1, minNum); + } + } + + private static int mathNode(final int selectNum) { + if (selectNum == 0) { + return 1; + } else { + return selectNum * mathNode(selectNum - 1); + } + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java index c8835ea89..6d40e14f4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/math/NumberUtil.java @@ -32,7 +32,6 @@ import java.util.Collection; *
  • one-jdk7-bug-thinking
  • * *

    - * TODO 需整理精简方法,去掉无用的重载方法。 * * @author Looly */ @@ -43,14 +42,6 @@ public class NumberUtil { */ private static final int DEFAULT_DIV_SCALE = 10; - /** - * 0-20对应的阶乘,超过20的阶乘会超过Long.MAX_VALUE - */ - private static final long[] FACTORIALS = new long[]{ - 1L, 1L, 2L, 6L, 24L, 120L, 720L, 5040L, 40320L, 362880L, 3628800L, 39916800L, 479001600L, 6227020800L, - 87178291200L, 1307674368000L, 20922789888000L, 355687428096000L, 6402373705728000L, 121645100408832000L, - 2432902008176640000L}; - /** * 提供精确的加法运算
    * 如果传入多个值为null或者空,则返回0 @@ -263,7 +254,7 @@ public class NumberUtil { */ public static BigDecimal div(Number v1, final Number v2, int scale, final RoundingMode roundingMode) { Assert.notNull(v2, "Divisor must be not null !"); - if(null == v1){ + if (null == v1) { v1 = BigDecimal.ZERO; } if (v1 instanceof BigDecimal && v2 instanceof BigDecimal) { @@ -757,7 +748,7 @@ public class NumberUtil { * @return 是否为整数 */ public static boolean isInteger(final String s) { - if(StrUtil.isBlank(s)) { + if (StrUtil.isBlank(s)) { return false; } try { @@ -777,7 +768,7 @@ public class NumberUtil { * @since 4.0.0 */ public static boolean isLong(final String s) { - if(StrUtil.isBlank(s)) { + if (StrUtil.isBlank(s)) { return false; } try { @@ -795,7 +786,7 @@ public class NumberUtil { * @return 是否为{@link Double}类型 */ public static boolean isDouble(final String s) { - if(StrUtil.isBlank(s)) { + if (StrUtil.isBlank(s)) { return false; } try { @@ -827,52 +818,58 @@ public class NumberUtil { // ------------------------------------------------------------------------------------------- range /** - * 从0开始给定范围内的整数列表,步进为1 + * 生成一个从0开始的数字列表
    * - * @param stop 结束(包含) - * @return 整数列表 - * @since 3.3.1 + * @param stopIncluded 结束的数字(不包含) + * @return 数字列表 */ - public static int[] range(final int stop) { - return range(0, stop); + public static int[] range(final int stopIncluded) { + return range(0, stopIncluded, 1); } /** - * 给定范围内的整数列表,步进为1 + * 生成一个数字列表
    + * 自动判定正序反序 * - * @param start 开始(包含) - * @param stop 结束(包含) - * @return 整数列表 + * @param startInclude 开始的数字(包含) + * @param stopIncluded 结束的数字(包含) + * @return 数字列表 */ - public static int[] range(final int start, final int stop) { - return range(start, stop, 1); + public static int[] range(final int startInclude, final int stopIncluded) { + return range(startInclude, stopIncluded, 1); } /** - * 给定范围内的整数列表 + * 生成一个数字列表
    + * 自动判定正序反序 * - * @param includeStart 开始(包含) - * @param includeEnd 结束(包含) - * @param step 步进 - * @return 整数列表 + * @param startInclude 开始的数字(包含) + * @param stopIncluded 结束的数字(不包含) + * @param step 步进 + * @return 数字列表 */ - public static int[] range(final int includeStart, final int includeEnd, int step) { - if (includeStart < includeEnd) { - step = Math.abs(step); - } else if (includeStart > includeEnd) { - step = -Math.abs(step); - } else {// start == end - return new int[]{includeStart}; + public static int[] range(int startInclude, int stopIncluded, int step) { + if (startInclude > stopIncluded) { + final int tmp = startInclude; + startInclude = stopIncluded; + stopIncluded = tmp; } - final int size = Math.abs((includeEnd - includeStart) / step) + 1; - final int[] values = new int[size]; - int index = 0; - for (int i = includeStart; (step > 0) ? i <= includeEnd : i >= includeEnd; i += step) { - values[index] = i; - index++; + if (step <= 0) { + step = 1; } - return values; + + final int deviation = stopIncluded + 1 - startInclude; + int length = deviation / step; + if (deviation % step != 0) { + length += 1; + } + final int[] range = new int[length]; + for (int i = 0; i < length; i++) { + range[i] = startInclude; + startInclude += step; + } + return range; } /** @@ -890,23 +887,23 @@ public class NumberUtil { /** * 将给定范围内的整数添加到已有集合中 * - * @param start 开始(包含) - * @param stop 结束(包含) - * @param step 步进 - * @param values 集合 + * @param startInclude 开始(包含) + * @param stopInclude 结束(包含) + * @param step 步进 + * @param values 集合 * @return 集合 */ - public static Collection appendRange(final int start, final int stop, int step, final Collection values) { - if (start < stop) { + public static Collection appendRange(final int startInclude, final int stopInclude, int step, final Collection values) { + if (startInclude < stopInclude) { step = Math.abs(step); - } else if (start > stop) { + } else if (startInclude > stopInclude) { step = -Math.abs(step); } else {// start == end - values.add(start); + values.add(startInclude); return values; } - for (int i = start; (step > 0) ? i <= stop : i >= stop; i += step) { + for (int i = startInclude; (step > 0) ? i <= stopInclude : i >= stopInclude; i += step) { values.add(i); } return values; @@ -914,177 +911,6 @@ public class NumberUtil { // ------------------------------------------------------------------------------------------- others - /** - * 计算阶乘 - *

    - * n! = n * (n-1) * ... * 2 * 1 - *

    - * - * @param n 阶乘起始 - * @return 结果 - * @since 5.6.0 - */ - public static BigInteger factorial(final BigInteger n) { - if (n.equals(BigInteger.ZERO)) { - return BigInteger.ONE; - } - return factorial(n, BigInteger.ZERO); - } - - /** - * 计算范围阶乘 - *

    - * factorial(start, end) = start * (start - 1) * ... * (end + 1) - *

    - * - * @param start 阶乘起始(包含) - * @param end 阶乘结束,必须小于起始(不包括) - * @return 结果 - * @since 5.6.0 - */ - public static BigInteger factorial(BigInteger start, BigInteger end) { - Assert.notNull(start, "Factorial start must be not null!"); - Assert.notNull(end, "Factorial end must be not null!"); - if (start.compareTo(BigInteger.ZERO) < 0 || end.compareTo(BigInteger.ZERO) < 0) { - throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be > 0, but got start={}, end={}", start, end)); - } - - if (start.equals(BigInteger.ZERO)) { - start = BigInteger.ONE; - } - - if (end.compareTo(BigInteger.ONE) < 0) { - end = BigInteger.ONE; - } - - BigInteger result = start; - end = end.add(BigInteger.ONE); - while (start.compareTo(end) > 0) { - start = start.subtract(BigInteger.ONE); - result = result.multiply(start); - } - return result; - } - - /** - * 计算范围阶乘 - *

    - * factorial(start, end) = start * (start - 1) * ... * (end + 1) - *

    - * - * @param start 阶乘起始(包含) - * @param end 阶乘结束,必须小于起始(不包括) - * @return 结果 - * @since 4.1.0 - */ - public static long factorial(final long start, final long end) { - // 负数没有阶乘 - if (start < 0 || end < 0) { - throw new IllegalArgumentException(StrUtil.format("Factorial start and end both must be >= 0, but got start={}, end={}", start, end)); - } - if (0L == start || start == end) { - return 1L; - } - if (start < end) { - return 0L; - } - return factorialMultiplyAndCheck(start, factorial(start - 1, end)); - } - - /** - * 计算范围阶乘中校验中间的计算是否存在溢出,factorial提前做了负数和0的校验,因此这里没有校验数字的正负 - * - * @param a 乘数 - * @param b 被乘数 - * @return 如果 a * b的结果没有溢出直接返回,否则抛出异常 - */ - private static long factorialMultiplyAndCheck(final long a, final long b) { - if (a <= Long.MAX_VALUE / b) { - return a * b; - } - throw new IllegalArgumentException(StrUtil.format("Overflow in multiplication: {} * {}", a, b)); - } - - /** - * 计算阶乘 - *

    - * n! = n * (n-1) * ... * 2 * 1 - *

    - * - * @param n 阶乘起始 - * @return 结果 - */ - public static long factorial(final long n) { - if (n < 0 || n > 20) { - throw new IllegalArgumentException(StrUtil.format("Factorial must have n >= 0 and n <= 20 for n!, but got n = {}", n)); - } - return FACTORIALS[(int) n]; - } - - /** - * 平方根算法
    - * 推荐使用 {@link Math#sqrt(double)} - * - * @param x 值 - * @return 平方根 - */ - public static long sqrt(long x) { - long y = 0; - long b = (~Long.MAX_VALUE) >>> 1; - while (b > 0) { - if (x >= y + b) { - x -= y + b; - y >>= 1; - y += b; - } else { - y >>= 1; - } - b >>= 2; - } - return y; - } - - /** - * 可以用于计算双色球、大乐透注数的方法
    - * 比如大乐透35选5可以这样调用processMultiple(7,5); 就是数学中的:C75=7*6/2*1 - * - * @param selectNum 选中小球个数 - * @param minNum 最少要选中多少个小球 - * @return 注数 - */ - public static int processMultiple(final int selectNum, final int minNum) { - final int result; - result = mathSubNode(selectNum, minNum) / mathNode(selectNum - minNum); - return result; - } - - /** - * 最大公约数 - * - * @param m 第一个值 - * @param n 第二个值 - * @return 最大公约数 - */ - public static int divisor(int m, int n) { - while (m % n != 0) { - final int temp = m % n; - m = n; - n = temp; - } - return n; - } - - /** - * 最小公倍数 - * - * @param m 第一个值 - * @param n 第二个值 - * @return 最小公倍数 - */ - public static int multiple(final int m, final int n) { - return m * n / divisor(m, n); - } - /** * 获得数字对应的二进制字符串 * @@ -1121,86 +947,6 @@ public class NumberUtil { return Long.parseLong(binaryStr, 2); } - // ------------------------------------------------------------------------------------------- compare - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 - * @see Character#compare(char, char) - * @since 3.0.1 - */ - public static int compare(final char x, final char y) { - return Character.compare(x, y); - } - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 - * @see Double#compare(double, double) - * @since 3.0.1 - */ - public static int compare(final double x, final double y) { - return Double.compare(x, y); - } - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 - * @see Integer#compare(int, int) - * @since 3.0.1 - */ - public static int compare(final int x, final int y) { - return Integer.compare(x, y); - } - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 - * @see Long#compare(long, long) - * @since 3.0.1 - */ - public static int compare(final long x, final long y) { - return Long.compare(x, y); - } - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回小于0的数,x>y返回大于0的数 - * @see Short#compare(short, short) - * @since 3.0.1 - */ - public static int compare(final short x, final short y) { - return Short.compare(x, y); - } - - /** - * 比较两个值的大小 - * - * @param x 第一个值 - * @param y 第二个值 - * @return x==y返回0,x<y返回-1,x>y返回1 - * @see Byte#compare(byte, byte) - * @since 3.0.1 - */ - public static int compare(final byte x, final byte y) { - return Byte.compare(x, y); - } - /** * 比较大小,参数1 > 参数2 返回true * @@ -1333,176 +1079,6 @@ public class NumberUtil { return CharUtil.equals(c1, c2, ignoreCase); } - /** - * 取最小值 - * - * @param 元素类型 - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(Comparable[]) - * @since 4.0.7 - */ - public static > T min(final T[] numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(long...) - * @since 4.0.7 - */ - public static long min(final long... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(int...) - * @since 4.0.7 - */ - public static int min(final int... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(short...) - * @since 4.0.7 - */ - public static short min(final short... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(double...) - * @since 4.0.7 - */ - public static double min(final double... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(float...) - * @since 4.0.7 - */ - public static float min(final float... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最小值 - * - * @param numberArray 数字数组 - * @return 最小值 - * @see ArrayUtil#min(Comparable[]) - * @since 5.0.8 - */ - public static BigDecimal min(final BigDecimal... numberArray) { - return ArrayUtil.min(numberArray); - } - - /** - * 取最大值 - * - * @param 元素类型 - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(Comparable[]) - * @since 4.0.7 - */ - public static > T max(final T[] numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(long...) - * @since 4.0.7 - */ - public static long max(final long... numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(int...) - * @since 4.0.7 - */ - public static int max(final int... numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(short...) - * @since 4.0.7 - */ - public static short max(final short... numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(double...) - * @since 4.0.7 - */ - public static double max(final double... numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(float...) - * @since 4.0.7 - */ - public static float max(final float... numberArray) { - return ArrayUtil.max(numberArray); - } - - /** - * 取最大值 - * - * @param numberArray 数字数组 - * @return 最大值 - * @see ArrayUtil#max(Comparable[]) - * @since 5.0.8 - */ - public static BigDecimal max(final BigDecimal... numberArray) { - return ArrayUtil.max(numberArray); - } - /** * 数字转字符串
    * 调用{@link Number#toString()},并去除尾小数点儿后多余的0 @@ -2201,21 +1777,4 @@ public class NumberUtil { return false == isOdd(num); } - // ------------------------------------------------------------------------------------------- Private method start - private static int mathSubNode(final int selectNum, final int minNum) { - if (selectNum == minNum) { - return 1; - } else { - return selectNum * mathSubNode(selectNum - 1, minNum); - } - } - - private static int mathNode(final int selectNum) { - if (selectNum == 0) { - return 1; - } else { - return selectNum * mathNode(selectNum - 1); - } - } - // ------------------------------------------------------------------------------------------- Private method end } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java index f6b54825b..9c7e4e8c7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java @@ -462,63 +462,6 @@ public class PrimitiveArrayUtil { return result; } - // ---------------------------------------------------------------------- range - - /** - * 生成一个从0开始的数字列表
    - * - * @param excludedEnd 结束的数字(不包含) - * @return 数字列表 - */ - public static int[] range(final int excludedEnd) { - return range(0, excludedEnd, 1); - } - - /** - * 生成一个数字列表
    - * 自动判定正序反序 - * - * @param includedStart 开始的数字(包含) - * @param excludedEnd 结束的数字(不包含) - * @return 数字列表 - */ - public static int[] range(final int includedStart, final int excludedEnd) { - return range(includedStart, excludedEnd, 1); - } - - /** - * 生成一个数字列表
    - * 自动判定正序反序 - * - * @param includedStart 开始的数字(包含) - * @param excludedEnd 结束的数字(不包含) - * @param step 步进 - * @return 数字列表 - */ - public static int[] range(int includedStart, int excludedEnd, int step) { - if (includedStart > excludedEnd) { - final int tmp = includedStart; - includedStart = excludedEnd; - excludedEnd = tmp; - } - - if (step <= 0) { - step = 1; - } - - final int deviation = excludedEnd - includedStart; - int length = deviation / step; - if (deviation % step != 0) { - length += 1; - } - final int[] range = new int[length]; - for (int i = 0; i < length; i++) { - range[i] = includedStart; - includedStart += step; - } - return range; - } - // ---------------------------------------------------------------------- split /** diff --git a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java index a7b8bc6c4..c376f2b60 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java @@ -512,7 +512,7 @@ public class RandomUtil { * @since 5.2.1 */ public static int[] randomInts(final int length) { - final int[] range = ArrayUtil.range(length); + final int[] range = NumberUtil.range(length); for (int i = 0; i < length; i++) { final int random = randomInt(i, length); ArrayUtil.swap(range, i, random); diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/PartitionIterTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/PartitionIterTest.java index e4c02049c..4d11d678f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/PartitionIterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/PartitionIterTest.java @@ -3,7 +3,7 @@ package cn.hutool.core.collection; import cn.hutool.core.collection.iter.LineIter; import cn.hutool.core.collection.iter.PartitionIter; import cn.hutool.core.io.resource.ResourceUtil; -import cn.hutool.core.math.NumberUtil; +import cn.hutool.core.util.ArrayUtil; import org.junit.Assert; import org.junit.Test; @@ -26,7 +26,7 @@ public class PartitionIterTest { final PartitionIter iter = new PartitionIter<>(list.iterator(), 3); int max = 0; for (final List lines : iter) { - max = NumberUtil.max(max, NumberUtil.max(lines.toArray(new Integer[0]))); + max = ArrayUtil.max(max, ArrayUtil.max(lines.toArray(new Integer[0]))); } Assert.assertEquals(45, max); } diff --git a/hutool-core/src/test/java/cn/hutool/core/math/MathUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/math/MathUtilTest.java new file mode 100644 index 000000000..b196b3dbf --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/math/MathUtilTest.java @@ -0,0 +1,44 @@ +package cn.hutool.core.math; + +import org.junit.Assert; +import org.junit.Test; + +import java.math.BigInteger; + +public class MathUtilTest { + @Test + public void factorialTest(){ + long factorial = MathUtil.factorial(0); + Assert.assertEquals(1, factorial); + + Assert.assertEquals(1L, MathUtil.factorial(1)); + Assert.assertEquals(1307674368000L, MathUtil.factorial(15)); + Assert.assertEquals(2432902008176640000L, MathUtil.factorial(20)); + + factorial = MathUtil.factorial(5, 0); + Assert.assertEquals(120, factorial); + factorial = MathUtil.factorial(5, 1); + Assert.assertEquals(120, factorial); + + Assert.assertEquals(5, MathUtil.factorial(5, 4)); + Assert.assertEquals(2432902008176640000L, MathUtil.factorial(20, 0)); + } + + @Test + public void factorialTest2(){ + long factorial = MathUtil.factorial(new BigInteger("0")).longValue(); + Assert.assertEquals(1, factorial); + + Assert.assertEquals(1L, MathUtil.factorial(new BigInteger("1")).longValue()); + Assert.assertEquals(1307674368000L, MathUtil.factorial(new BigInteger("15")).longValue()); + Assert.assertEquals(2432902008176640000L, MathUtil.factorial(20)); + + factorial = MathUtil.factorial(new BigInteger("5"), new BigInteger("0")).longValue(); + Assert.assertEquals(120, factorial); + factorial = MathUtil.factorial(new BigInteger("5"), BigInteger.ONE).longValue(); + Assert.assertEquals(120, factorial); + + Assert.assertEquals(5, MathUtil.factorial(new BigInteger("5"), new BigInteger("4")).longValue()); + Assert.assertEquals(2432902008176640000L, MathUtil.factorial(new BigInteger("20"), BigInteger.ZERO).longValue()); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 5656f92df..5d9d2a798 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -167,27 +167,6 @@ public class ArrayUtilTest { Assert.assertEquals(values[2], cast[2]); } - @Test - public void rangeTest() { - final int[] range = ArrayUtil.range(0, 10); - Assert.assertEquals(0, range[0]); - Assert.assertEquals(1, range[1]); - Assert.assertEquals(2, range[2]); - Assert.assertEquals(3, range[3]); - Assert.assertEquals(4, range[4]); - Assert.assertEquals(5, range[5]); - Assert.assertEquals(6, range[6]); - Assert.assertEquals(7, range[7]); - Assert.assertEquals(8, range[8]); - Assert.assertEquals(9, range[9]); - } - - @Test(expected = NegativeArraySizeException.class) - public void rangeMinTest() { - //noinspection ResultOfMethodCallIgnored - ArrayUtil.range(0, Integer.MIN_VALUE); - } - @Test public void maxTest() { final int max = ArrayUtil.max(1, 2, 13, 4, 5); diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 183eb2a4b..c89dc1f1e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -6,7 +6,6 @@ import org.junit.Assert; import org.junit.Test; import java.math.BigDecimal; -import java.math.BigInteger; import java.math.RoundingMode; /** @@ -262,18 +261,6 @@ public class NumberUtilTest { Assert.assertEquals("1234.56", bigDecimal.toString()); } - @Test - public void maxTest() { - final int max = NumberUtil.max(5,4,3,6,1); - Assert.assertEquals(6, max); - } - - @Test - public void minTest() { - final int min = NumberUtil.min(5,4,3,6,1); - Assert.assertEquals(1, min); - } - @Test public void parseIntTest() { int number = NumberUtil.parseInt("0xFF"); @@ -362,42 +349,6 @@ public class NumberUtilTest { Assert.assertEquals(0, number); } - @Test - public void factorialTest(){ - long factorial = NumberUtil.factorial(0); - Assert.assertEquals(1, factorial); - - Assert.assertEquals(1L, NumberUtil.factorial(1)); - Assert.assertEquals(1307674368000L, NumberUtil.factorial(15)); - Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20)); - - factorial = NumberUtil.factorial(5, 0); - Assert.assertEquals(120, factorial); - factorial = NumberUtil.factorial(5, 1); - Assert.assertEquals(120, factorial); - - Assert.assertEquals(5, NumberUtil.factorial(5, 4)); - Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20, 0)); - } - - @Test - public void factorialTest2(){ - long factorial = NumberUtil.factorial(new BigInteger("0")).longValue(); - Assert.assertEquals(1, factorial); - - Assert.assertEquals(1L, NumberUtil.factorial(new BigInteger("1")).longValue()); - Assert.assertEquals(1307674368000L, NumberUtil.factorial(new BigInteger("15")).longValue()); - Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20)); - - factorial = NumberUtil.factorial(new BigInteger("5"), new BigInteger("0")).longValue(); - Assert.assertEquals(120, factorial); - factorial = NumberUtil.factorial(new BigInteger("5"), BigInteger.ONE).longValue(); - Assert.assertEquals(120, factorial); - - Assert.assertEquals(5, NumberUtil.factorial(new BigInteger("5"), new BigInteger("4")).longValue()); - Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(new BigInteger("20"), BigInteger.ZERO).longValue()); - } - @Test public void isPowerOfTwoTest() { Assert.assertFalse(NumberUtil.isPowerOfTwo(-1)); @@ -462,4 +413,25 @@ public class NumberUtilTest { Assert.assertFalse(NumberUtil.isDouble(" ")); } + @Test + public void rangeTest() { + final int[] range = NumberUtil.range(0, 10); + Assert.assertEquals(0, range[0]); + Assert.assertEquals(1, range[1]); + Assert.assertEquals(2, range[2]); + Assert.assertEquals(3, range[3]); + Assert.assertEquals(4, range[4]); + Assert.assertEquals(5, range[5]); + Assert.assertEquals(6, range[6]); + Assert.assertEquals(7, range[7]); + Assert.assertEquals(8, range[8]); + Assert.assertEquals(9, range[9]); + Assert.assertEquals(10, range[10]); + } + + @Test(expected = NegativeArraySizeException.class) + public void rangeMinTest() { + //noinspection ResultOfMethodCallIgnored + NumberUtil.range(0, Integer.MIN_VALUE); + } }