ref[move]: move NumberUtils

This commit is contained in:
godotg
2023-09-02 19:43:23 +08:00
parent 793319298a
commit 4d015a1fb8
5 changed files with 5 additions and 80 deletions
@@ -13,7 +13,6 @@
package com.zfoo.protocol.collection;
import com.zfoo.protocol.collection.model.NaturalComparator;
import com.zfoo.protocol.model.Pair;
import com.zfoo.protocol.util.AssertionUtils;
import com.zfoo.protocol.util.IOUtils;
@@ -131,11 +130,11 @@ public abstract class CollectionUtils {
* @return a new sorted List, containing the elements of Collection a and b
*/
public static <T extends Comparable<? super T>> List<T> collate(List<? extends T> aList, List<? extends T> bList) {
return collate(aList, bList, NaturalComparator.getInstance(), true);
return collate(aList, bList, Comparator.naturalOrder(), true);
}
public static <T extends Comparable<? super T>> List<T> collate(List<? extends T> aList, List<? extends T> bList, boolean includeDuplicates) {
return collate(aList, bList, NaturalComparator.getInstance(), includeDuplicates);
return collate(aList, bList, Comparator.naturalOrder(), includeDuplicates);
}
public static <T> List<T> collate(List<T> aList, List<T> bList, Comparator<T> comparator) {
@@ -1,72 +0,0 @@
/*
* Copyright (C) 2020 The zfoo Authors
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.collection.model;
import java.util.Comparator;
public class NaturalComparator<E extends Comparable<? super E>> implements Comparator<E> {
/**
* The singleton instance.
*/
private static final NaturalComparator<?> INSTANCE = new NaturalComparator<>();
//-----------------------------------------------------------------------
/**
* Constructor whose use should be avoided.
* <p>
* Please use the {@link #getInstance()} method whenever possible.
*/
public NaturalComparator() {
super();
}
//-----------------------------------------------------------------------
/**
* Gets the singleton instance of a ComparableComparator.
* <p>
* Developers are encouraged to use the comparator returned from this method
* instead of constructing a new instance to reduce allocation and GC overhead
* when multiple comparable comparators may be used in the same VM.
*
* @param <E> the element type
* @return the singleton ComparableComparator
*/
public static <E extends Comparable<? super E>> NaturalComparator<E> getInstance() {
return (NaturalComparator<E>) INSTANCE;
}
//-----------------------------------------------------------------------
/**
* Compare the two {@link Comparable Comparable} arguments.
* This method is equivalent to:
* <pre>((Comparable)obj1).compareTo(obj2)</pre>
*
* @param a the first object to compare
* @param b the second object to compare
* @return negative if obj1 is less, positive if greater, zero if equal
* @throws NullPointerException if <i>obj1</i> is <code>null</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
* @throws ClassCastException if <i>obj1</i> is not a <code>Comparable</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
*/
@Override
public int compare(final E a, final E b) {
return a.compareTo(b);
}
}
@@ -0,0 +1,992 @@
/*
* Copyright (C) 2020 The zfoo Authors
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package com.zfoo.protocol.util;
import com.zfoo.protocol.collection.ArrayUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Collection;
/**
* 数字工具类<br>
* BigDecimal(double val)构造方法的结果有一定的不可预知性,例如:
*
* <pre>
* new BigDecimal(0.1)
* </pre>
* <p>
* 表示的不是0.1而是0.1000000000000000055511151231257827021181583404541015625
* <p>
* 这是因为0.1无法准确的表示为double。因此应该使用new BigDecimal(String)。
*
* @author godotg
* @version 3.0
*/
public abstract class NumberUtils {
/**
* 默认除法运算精度
*/
private static final int DEFAULT_DIV_SCALE = 10;
/**
* 提供精确的加法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被加值
* @return 和
*/
public static BigDecimal add(Number... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
Number value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.add(new BigDecimal(value.toString()));
}
}
return result;
}
/**
* 提供精确的加法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被加值
* @return 求和
*/
public static BigDecimal add(String... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
String value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value);
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.add(new BigDecimal(value));
}
}
return result;
}
/**
* 提供精确的加法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被加值
* @return 求和
*/
public static BigDecimal add(BigDecimal... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
BigDecimal value = values[0];
BigDecimal result = null == value ? BigDecimal.ZERO : value;
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.add(value);
}
}
return result;
}
/**
* 提供精确的减法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被减值
* @return 差
*/
public static BigDecimal sub(Number... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
Number value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.subtract(new BigDecimal(value.toString()));
}
}
return result;
}
/**
* 提供精确的减法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被减值
* @return 差
*/
public static BigDecimal sub(String... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
String value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value);
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.subtract(new BigDecimal(value));
}
}
return result;
}
/**
* 提供精确的减法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被减值
* @return 差
*/
public static BigDecimal sub(BigDecimal... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
BigDecimal value = values[0];
BigDecimal result = null == value ? BigDecimal.ZERO : value;
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.subtract(value);
}
}
return result;
}
/**
* 提供精确的乘法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被乘值
* @return 积
*/
public static BigDecimal mul(Number... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
Number value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.multiply(new BigDecimal(value.toString()));
}
}
return result;
}
/**
* 提供精确的乘法运算
*
* @param a 被乘数
* @param b 乘数
* @return 积
*/
public static BigDecimal mul(String a, String b) {
return mul(new BigDecimal(a), new BigDecimal(b));
}
/**
* 提供精确的乘法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被乘值
* @return 积
*/
public static BigDecimal mul(String... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
String value = values[0];
BigDecimal result = new BigDecimal(null == value ? "0" : value);
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.multiply(new BigDecimal(value));
}
}
return result;
}
/**
* 提供精确的乘法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被乘值
* @return 积
*/
public static BigDecimal mul(BigDecimal... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
BigDecimal value = values[0];
BigDecimal result = null == value ? BigDecimal.ZERO : value;
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.multiply(value);
}
}
return result;
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况的时候,精确到小数点后10位,后面的四舍五入
*
* @param a 被除数
* @param b 除数
* @return 两个参数的商
*/
public static BigDecimal div(Number a, Number b) {
return div(a, b, DEFAULT_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况的时候,精确到小数点后10位,后面的四舍五入
*
* @param a 被除数
* @param b 除数
* @return 两个参数的商
*/
public static BigDecimal div(String a, String b) {
return div(a, b, DEFAULT_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度,后面的四舍五入
*
* @param a 被除数
* @param b 除数
* @param scale 精确度,如果为负值,取绝对值
* @return 两个参数的商
*/
public static BigDecimal div(Number a, Number b, int scale) {
return div(a, b, scale, RoundingMode.HALF_UP);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度,后面的四舍五入
*
* @param a 被除数
* @param b 除数
* @param scale 精确度,如果为负值,取绝对值
* @return 两个参数的商
*/
public static BigDecimal div(String a, String b, int scale) {
return div(a, b, scale, RoundingMode.HALF_UP);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度
*
* @param a 被除数
* @param b 除数
* @param scale 精确度,如果为负值,取绝对值
* @param roundingMode 保留小数的模式 {@link RoundingMode}
* @return 两个参数的商
*/
public static BigDecimal div(Number a, Number b, int scale, RoundingMode roundingMode) {
return div(a.toString(), b.toString(), scale, roundingMode);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度
*
* @param a 被除数
* @param b 除数
* @param scale 精确度,如果为负值,取绝对值
* @param roundingMode 保留小数的模式 {@link RoundingMode}
* @return 两个参数的商
*/
public static BigDecimal div(String a, String b, int scale, RoundingMode roundingMode) {
return div(new BigDecimal(a), new BigDecimal(b), scale, roundingMode);
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度
*
* @param a 被除数
* @param b 除数
* @param scale 精确度,如果为负值,取绝对值
* @param roundingMode 保留小数的模式 {@link RoundingMode}
* @return 两个参数的商
*/
public static BigDecimal div(BigDecimal a, BigDecimal b, int scale, RoundingMode roundingMode) {
AssertionUtils.notNull(b, "Divisor must be not null !");
if (null == a) {
return BigDecimal.ZERO;
}
if (scale < 0) {
scale = -scale;
}
return a.divide(b, scale, roundingMode);
}
/**
* 提供精确的乘法运算<br>
* 如果传入多个值为null或者空,则返回0
*
* @param values 多个被乘值
* @return 积
*/
public static BigDecimal div(BigDecimal... values) {
if (ArrayUtils.isEmpty(values)) {
return BigDecimal.ZERO;
}
BigDecimal value = values[0];
BigDecimal result = null == value ? BigDecimal.ZERO : value;
for (int i = 1; i < values.length; i++) {
value = values[i];
if (null != value) {
result = result.divide(value);
}
}
return result;
}
// ------------------------------------------------------------------------------------------- round
/**
* 保留固定位数小数<br>
* 采用四舍五入策略 {@link RoundingMode#HALF_UP}<br>
* 例如保留2位小数:123.456789 =》 123.46
*
* @param v 值
* @param scale 保留小数位数
* @return 新值
*/
public static BigDecimal round(double v, int scale) {
return round(v, scale, RoundingMode.HALF_UP);
}
/**
* 保留固定位数小数<br>
* 采用四舍五入策略 {@link RoundingMode#HALF_UP}<br>
* 例如保留2位小数:123.456789 =》 123.46
*
* @param numberStr 数字值的字符串表现形式
* @param scale 保留小数位数
* @return 新值
*/
public static BigDecimal round(String numberStr, int scale) {
return round(numberStr, scale, RoundingMode.HALF_UP);
}
/**
* 保留固定位数小数<br>
* 采用四舍五入策略 {@link RoundingMode#HALF_UP}<br>
* 例如保留2位小数:123.456789 =》 123.46
*
* @param number 数字值
* @param scale 保留小数位数
* @return 新值
*/
public static BigDecimal round(BigDecimal number, int scale) {
return round(number, scale, RoundingMode.HALF_UP);
}
/**
* 保留固定位数小数<br>
* 例如保留四位小数:123.456789 =》 123.4567
*
* @param v 值
* @param scale 保留小数位数
* @param roundingMode 保留小数的模式 {@link RoundingMode}
* @return 新值
*/
public static BigDecimal round(double v, int scale, RoundingMode roundingMode) {
return round(Double.toString(v), scale, roundingMode);
}
/**
* 保留固定位数小数<br>
* 例如保留四位小数:123.456789 =》 123.4567
*
* @param numberStr 数字值的字符串表现形式
* @param scale 保留小数位数,如果传入小于0,则默认0
* @param roundingMode 保留小数的模式 {@link RoundingMode},如果传入null则默认四舍五入
* @return 新值
*/
public static BigDecimal round(String numberStr, int scale, RoundingMode roundingMode) {
AssertionUtils.isTrue(StringUtils.isNotBlank(numberStr));
if (scale < 0) {
scale = 0;
}
return round(toBigDecimal(numberStr), scale, roundingMode);
}
/**
* 保留固定位数小数<br>
* 例如保留四位小数:123.456789 =》 123.4567
*
* @param number 数字值
* @param scale 保留小数位数,如果传入小于0,则默认0
* @param roundingMode 保留小数的模式 {@link RoundingMode},如果传入null则默认四舍五入
* @return 新值
*/
public static BigDecimal round(BigDecimal number, int scale, RoundingMode roundingMode) {
if (null == number) {
number = BigDecimal.ZERO;
}
if (scale < 0) {
scale = 0;
}
if (null == roundingMode) {
roundingMode = RoundingMode.HALF_UP;
}
return number.setScale(scale, roundingMode);
}
/**
* 四舍六入五成双计算法
* <p>
* 四舍六入五成双是一种比较精确比较科学的计数保留法,是一种数字修约规则。
* </p>
*
* <pre>
* 算法规则:
* 四舍六入五考虑,
* 五后非零就进一,
* 五后皆零看奇偶,
* 五前为偶应舍去,
* 五前为奇要进一。
* </pre>
*
* @param number 需要科学计算的数据
* @param scale 保留的小数位
* @return 结果
*/
public static BigDecimal roundHalfEven(Number number, int scale) {
return roundHalfEven(toBigDecimal(number), scale);
}
/**
* 四舍六入五成双计算法
* <p>
* 四舍六入五成双是一种比较精确比较科学的计数保留法,是一种数字修约规则。
* </p>
*
* <pre>
* 算法规则:
* 四舍六入五考虑,
* 五后非零就进一,
* 五后皆零看奇偶,
* 五前为偶应舍去,
* 五前为奇要进一。
* </pre>
*
* @param value 需要科学计算的数据
* @param scale 保留的小数位
* @return 结果
*/
public static BigDecimal roundHalfEven(BigDecimal value, int scale) {
return round(value, scale, RoundingMode.HALF_EVEN);
}
/**
* 保留固定小数位数,舍去多余位数
*
* @param number 需要科学计算的数据
* @param scale 保留的小数位
* @return 结果
*/
public static BigDecimal roundDown(Number number, int scale) {
return roundDown(toBigDecimal(number), scale);
}
/**
* 保留固定小数位数,舍去多余位数
*
* @param value 需要科学计算的数据
* @param scale 保留的小数位
* @return 结果
*/
public static BigDecimal roundDown(BigDecimal value, int scale) {
return round(value, scale, RoundingMode.DOWN);
}
// ------------------------------------------------------------------------------------------- decimalFormat
/**
* 格式化double<br>
* 对 {@link DecimalFormat} 做封装<br>
*
* @param pattern 格式 格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。<br>
* <ul>
* <li>0 =》 取一位整数</li>
* <li>0.00 =》 取一位整数和两位小数</li>
* <li>00.000 =》 取两位整数和三位小数</li>
* <li># =》 取所有整数部分</li>
* <li>#.##% =》 以百分比方式计数,并取两位小数</li>
* <li>#.#####E0 =》 显示为科学计数法,并取五位小数</li>
* <li>,### =》 每三位以逗号进行分隔,例如:299,792,458</li>
* <li>光速大小为每秒,###米 =》 将格式嵌入文本</li>
* </ul>
* @param value 值
* @return 格式化后的值
*/
public static String decimalFormat(String pattern, double value) {
return new DecimalFormat(pattern).format(value);
}
/**
* 格式化double<br>
* 对 {@link DecimalFormat} 做封装<br>
*
* @param pattern 格式 格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。<br>
* <ul>
* <li>0 =》 取一位整数</li>
* <li>0.00 =》 取一位整数和两位小数</li>
* <li>00.000 =》 取两位整数和三位小数</li>
* <li># =》 取所有整数部分</li>
* <li>#.##% =》 以百分比方式计数,并取两位小数</li>
* <li>#.#####E0 =》 显示为科学计数法,并取五位小数</li>
* <li>,### =》 每三位以逗号进行分隔,例如:299,792,458</li>
* <li>光速大小为每秒,###米 =》 将格式嵌入文本</li>
* </ul>
* @param value 值
* @return 格式化后的值
*/
public static String decimalFormat(String pattern, long value) {
return new DecimalFormat(pattern).format(value);
}
/**
* 格式化金额输出,每三位用逗号分隔
*
* @param value 金额
* @return 格式化后的值
*/
public static String decimalFormatMoney(double value) {
return decimalFormat(",##0.00", value);
}
/**
* 格式化百分比,小数采用四舍五入方式
*
* @param number 值
* @param scale 保留小数位数
* @return 百分比
*/
public static String formatPercent(double number, int scale) {
final NumberFormat format = NumberFormat.getPercentInstance();
format.setMaximumFractionDigits(scale);
return format.format(number);
}
// ------------------------------------------------------------------------------------------- isXXX
/**
* 判断String是否是整数<br>
* 支持8、10、16进制
*
* @param s String
* @return 是否为整数
*/
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch (NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是Long类型<br>
* 支持8、10、16进制
*
* @param s String
* @return 是否为{@link Long}类型
*/
public static boolean isLong(String s) {
try {
Long.parseLong(s);
} catch (NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是浮点数
*
* @param s String
* @return 是否为{@link Double}类型
*/
public static boolean isDouble(String s) {
try {
Double.parseDouble(s);
return s.contains(".");
} catch (NumberFormatException e) {
return false;
}
}
/**
* 判断字符串是否全部都为数字
* <pre>
* StringUtils.isNumeric(null) = false
* StringUtils.isNumeric("") = false
* StringUtils.isNumeric(" ") = false
* StringUtils.isNumeric("123") = true
* StringUtils.isNumeric("\u0967\u0968\u0969") = true
* StringUtils.isNumeric("12 3") = false
* StringUtils.isNumeric("ab2c") = false
* StringUtils.isNumeric("12-3") = false
* StringUtils.isNumeric("12.3") = false
* StringUtils.isNumeric("-123") = false
* StringUtils.isNumeric("+123") = false
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if only contains digits, and is non-null
*/
public static boolean isNumeric(final CharSequence cs) {
if (StringUtils.isEmpty(cs)) {
return false;
}
return cs.chars().allMatch(it -> Character.isDigit(it));
}
/**
* 是否是质数(素数)<br>
* 质数表的质数又称素数。指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。
*
* @param n 数字
* @return 是否是质数
*/
public static boolean isPrimes(int n) {
AssertionUtils.isTrue(n > 1, "The number must be > 1");
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------------------- range
/**
* 从0开始给定范围内的整数列表,步进为1
*
* @param stop 结束(包含)
* @return 整数列表
*/
public static int[] range(int stop) {
return range(0, stop);
}
/**
* 给定范围内的整数列表,步进为1
*
* @param start 开始(包含)
* @param stop 结束(包含)
* @return 整数列表
*/
public static int[] range(int start, int stop) {
return range(start, stop, 1);
}
/**
* 给定范围内的整数列表
*
* @param start 开始(包含)
* @param stop 结束(包含)
* @param step 步进
* @return 整数列表
*/
public static int[] range(int start, int stop, int step) {
if (start < stop) {
step = Math.abs(step);
} else if (start > stop) {
step = -Math.abs(step);
} else {// start == end
return new int[]{start};
}
int size = Math.abs((stop - start) / step) + 1;
int[] values = new int[size];
int index = 0;
for (int i = start; (step > 0) ? i <= stop : i >= stop; i += step) {
values[index] = i;
index++;
}
return values;
}
/**
* 将给定范围内的整数添加到已有集合中,步进为1
*
* @param start 开始(包含)
* @param stop 结束(包含)
* @param values 集合
* @return 集合
*/
public static Collection<Integer> appendRange(int start, int stop, Collection<Integer> values) {
return appendRange(start, stop, 1, values);
}
/**
* 将给定范围内的整数添加到已有集合中
*
* @param start 开始(包含)
* @param stop 结束(包含)
* @param step 步进
* @param values 集合
* @return 集合
*/
public static Collection<Integer> appendRange(int start, int stop, int step, Collection<Integer> values) {
if (start < stop) {
step = Math.abs(step);
} else if (start > stop) {
step = -Math.abs(step);
} else {// start == end
values.add(start);
return values;
}
for (int i = start; (step > 0) ? i <= stop : i >= stop; i += step) {
values.add(i);
}
return values;
}
// ------------------------------------------------------------------------------------------- others
/**
* 计算阶乘
* <p>
* n! = n * (n-1) * ... * end
* </p>
*
* @param start 阶乘起始
* @param end 阶乘结束
* @return 结果
*/
public static long factorial(long start, long end) {
if (start < end) {
return 0L;
}
if (start == end) {
return 1L;
}
return start * factorial(start - 1, end);
}
/**
* 计算阶乘
* <p>
* n! = n * (n-1) * ... * 2 * 1
* </p>
*
* @param n 阶乘起始
* @return 结果
*/
public static long factorial(long n) {
return factorial(n, 1);
}
/**
* 平方根算法<br>
* 推荐使用 {@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;
}
/**
* 最大公约数
*
* @param m 第一个值
* @param n 第二个值
* @return 最大公约数
*/
public static int divisor(int m, int n) {
while (m % n != 0) {
int temp = m % n;
m = n;
n = temp;
}
return n;
}
/**
* 最小公倍数
*
* @param m 第一个值
* @param n 第二个值
* @return 最小公倍数
*/
public static int multiple(int m, int n) {
return m * n / divisor(m, n);
}
/**
* 获得数字对应的二进制字符串
*
* @param number 数字
* @return 二进制字符串
*/
public static String getBinaryStr(Number number) {
if (number instanceof Long) {
return Long.toBinaryString((Long) number);
} else if (number instanceof Integer) {
return Integer.toBinaryString((Integer) number);
} else {
return Long.toBinaryString(number.longValue());
}
}
/**
* 二进制转int
*
* @param binaryStr 二进制字符串
* @return int
*/
public static int binaryToInt(String binaryStr) {
return Integer.parseInt(binaryStr, 2);
}
/**
* 二进制转long
*
* @param binaryStr 二进制字符串
* @return long
*/
public static long binaryToLong(String binaryStr) {
return Long.parseLong(binaryStr, 2);
}
// ------------------------------------------------------------------------------------------- compare
/**
* 数字转{@link BigDecimal}
*
* @param number 数字
* @return {@link BigDecimal}
*/
public static BigDecimal toBigDecimal(Number number) {
if (null == number) {
return BigDecimal.ZERO;
}
return toBigDecimal(number.toString());
}
/**
* 数字转{@link BigDecimal}
*
* @param number 数字
* @return {@link BigDecimal}
*/
public static BigDecimal toBigDecimal(String number) {
return (null == number) ? BigDecimal.ZERO : new BigDecimal(number);
}
/**
* 判断两个数字是否相邻,例如1和2相邻,1和3不相邻<br>
* 判断方法为做差取绝对值判断是否为1
*
* @param number1 数字1
* @param number2 数字2
* @return 是否相邻
*/
public static boolean isBeside(long number1, long number2) {
return Math.abs(number1 - number2) == 1;
}
/**
* 判断两个数字是否相邻,例如1和2相邻,1和3不相邻<br>
* 判断方法为做差取绝对值判断是否为1
*
* @param number1 数字1
* @param number2 数字2
* @return 是否相邻
*/
public static boolean isBeside(int number1, int number2) {
return Math.abs(number1 - number2) == 1;
}
/**
* 提供精确的幂运算
*
* @param number 底数
* @param n 指数
* @return 幂的积
*/
public static BigDecimal pow(Number number, int n) {
return pow(toBigDecimal(number), n);
}
/**
* 提供精确的幂运算
*
* @param number 底数
* @param n 指数
* @return 幂的积
*/
public static BigDecimal pow(BigDecimal number, int n) {
return number.pow(n);
}
}