简述
最近有一个奇葩的需求,要求对数字做一些处理,大致是两种情况:
- 1.计算结果大于1时保留n为小数,当结果小于1时保留n位有效数字
- 2.计算结果大于1时保留整数位,小于1时,保留有效数字
实现效果
System.out.println("============连乘/连除/连加/连减==============");
System.out.println("2 x 5 x 8 x 10 = " + BigDecimalUtils.multiply(2, 5, 8, 10));
System.out.println("800/8/5/1 = " + BigDecimalUtils.divide(800, 8, 5, 1));
System.out.println("10/3 保留3位小数为: " + BigDecimalUtils.divide(10, 3, 3));
System.out.println("2 + 5 + 8 + 10 = " + BigDecimalUtils.add(2, 5, 8, 10));
System.out.println("2 - 5 - 8 - 10 = " + BigDecimalUtils.subtract(2, 5, 8, 10));
System.out.println("============精度大于一保留n位数或转整数,小于1时保留有效数字==============");
System.out.println("大于1保留三位小数 1.66665555=>" + BigDecimalUtils.setEffectiveNumber(1.66665555, 3));
System.out.println("小于1保留三位有效数字 0.00666655=>" + BigDecimalUtils.setEffectiveNumber(0.00666655, 3));
System.out.println("转整数位 1.66665555=>" + BigDecimalUtils.setEffectiveNumber(1.66665555, true));
System.out.println("0.00666655=>" + BigDecimalUtils.setEffectiveNumber(0.00666655, true));
实现代码
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
/**
* @author longzipeng
* 大数工具类
*/
public class BigDecimalUtils {
// 默认大数保留6位小数
public static final int DEFAULT_SCALE = 6;
// 默认大数除法 结果规则 四舍五入 向下舍入
public static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_DOWN;
// 默认保留n位有效数字
public static final int DEFAULT_PRECISION = 2;
// 大数一百、一千、一万
public static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
public static final BigDecimal ONE_THOUSAND = new BigDecimal("1000");
public static final BigDecimal TEN_THOUSAND = new BigDecimal("10000");
/**
* 通用大数比较大小
*/
public static int compareTo(Object number1, Object number2) {
return castToBigDecimal(number1).compareTo(castToBigDecimal(number2));
}
/**
* 通用大数判断相等
*/
public static boolean equal(Object number1, Object number2) {
return castToBigDecimal(number1).compareTo(castToBigDecimal(number2)) == 0;
}
/**
* 通用大数除法
*
* @param number1 运算的数1
* @param number2 运算的数2
* @return
*/
public static BigDecimal divide(Object number1, Object number2) {
BigDecimal b1 = castToBigDecimal(number1);
BigDecimal b2 = castToBigDecimal(number2);
return divide(b1, b2, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
}
// 重载大数方法除法
public static BigDecimal divide(Object number1, Object number2, int scale) {
BigDecimal b1 = castToBigDecimal(number1);
BigDecimal b2 = castToBigDecimal(number2);
return divide(b1, b2, scale, DEFAULT_ROUNDING_MODE);
}
// 如果结果为0 则返回0
public static BigDecimal divide(Object number1, Object number2, int scale, RoundingMode roundingMode) {
if (number2 == null || equal(number2, BigDecimal.ZERO)) {
return BigDecimal.ZERO;
}
BigDecimal b1 = castToBigDecimal(number1);
BigDecimal b2 = castToBigDecimal(number2);
return b1.divide(b2, scale, roundingMode);
}
public static BigDecimal divide(Object number1, Object number2, RoundingMode roundingMode) {
BigDecimal b1 = castToBigDecimal(number1);
BigDecimal b2 = castToBigDecimal(number2);
return divide(b1, b2, DEFAULT_SCALE, roundingMode);
}
/**
* number1 除n个数
*
* @param number1
* @param numbers
* @return
*/
public static BigDecimal divide(Object number1, Object... numbers) {
BigDecimal b1 = castToBigDecimal(number1);
if (numbers.length > 0) {
for (Object number : numbers) {
b1 = divide(b1, number, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
}
}
return b1;
}
/**
* 通用大数乘法
*
* @param number1
* @param number2
* @return
*/
public static BigDecimal multiply(Object number1, Object number2) {
BigDecimal b1 = castToBigDecimal(number1);
BigDecimal b2 = castToBigDecimal(number2);
return b1.multiply(b2);
}
/**
* 重载 n个数相乘
*
* @param numbers
* @return
*/
public static BigDecimal multiply(Object... numbers) {
BigDecimal ans = null;
if (numbers.length > 0) {
ans = castToBigDecimal(numbers[0]);
if (numbers.length > 1) { // 循环相乘
for (int i = 1; i < numbers.length; i++) {
ans = multiply(ans, numbers[i]);
}
}
}
return ans;
}
/**
* n个数相加
*
* @param numbers
* @return
*/
public static BigDecimal add(Object... numbers) {
BigDecimal ans = null;
if (numbers.length > 0) {
ans = castToBigDecimal(numbers[0]);
if (numbers.length > 1) { // 循环相乘
for (int i = 1; i < numbers.length; i++) {
ans = ans.add(castToBigDecimal(numbers[i]));
}
}
}
return ans;
}
/**
* n个数相减
*
* @param numbers
* @return
*/
public static BigDecimal subtract(Object... numbers) {
BigDecimal ans = null;
if (numbers.length > 0) {
ans = castToBigDecimal(numbers[0]);
if (numbers.length > 1) { // 循环相乘
for (int i = 1; i < numbers.length; i++) {
ans = ans.subtract(castToBigDecimal(numbers[i]));
}
}
}
return ans;
}
/**
* 默认向下取整
*
* @param number
* @return
*/
public static Integer castToInteger(BigDecimal number) {
return number.setScale(0, BigDecimal.ROUND_DOWN).intValue();
}
/**
* 将对象转化为大数
*
* @param obj
* @return
*/
public static BigDecimal castToBigDecimal(Object obj) {
if (obj == null) {
return BigDecimal.ZERO;
} else {
return obj instanceof BigDecimal ? (BigDecimal) obj : new BigDecimal(obj.toString());
}
}
/**
* 获取大数的小数位数
*
* @param b
* @return
*/
public static Integer getDecimalPlaces(BigDecimal b) {
if (b != null) {
// 判断如果为整数则直接返回0 过滤掉 xxx.000000的情况
if (equal(new BigDecimal(b.intValue()), b)) {
return 0;
}
// 否则进行位数判断
String str = b.toString();
int index = str.indexOf(".");
if (index == -1) {
return 0;
}
return str.substring(index + 1).length();
}
return null;
}
/**
* 保留n位小数
*
* @param b 大数
* @param scale 保留几位小数
* @param roundingMode 保留小数的规则
* @return
*/
public static BigDecimal setScala(BigDecimal b, int scale, RoundingMode roundingMode) {
return b.setScale(scale, roundingMode);
}
public static BigDecimal setScala(BigDecimal b, int scale) {
return b.setScale(scale, DEFAULT_ROUNDING_MODE);
}
public static BigDecimal setScala(BigDecimal b) {
return b.setScale(DEFAULT_SCALE);
}
/**
* 保留n位有效数字
* 1.如果为整数或者一位小数则直接返回,
* 2.多位小数,且前两位小数有值则保留两位小数。没值则保留两位有效数字
*
* @param b
* @param precision 有效数字精度
* @param isCastInt 是否保留整数
* @return
*/
public static BigDecimal setEffectiveNumber(Object b, int precision, boolean isCastInt) {
if (b == null) {
return null;
}
BigDecimal bBig = castToBigDecimal(b);
// 需要转换为int,那么大于1的话就转换为Int
if (isCastInt && bBig.compareTo(BigDecimal.ONE) > 0) {
return new BigDecimal(bBig.intValue());
}
// 获取小数位数
Integer decimalPlaces = getDecimalPlaces(bBig);
if (decimalPlaces != null) {
// 为整数返回整数部分 将 xx.000转换为xx
if (equal(decimalPlaces, Integer.valueOf(0))) {
return new BigDecimal(bBig.intValue());
}
// 一位小数则直接返回
if (decimalPlaces.equals(Integer.valueOf("1"))) {
return bBig;
}
// 值大于0时 保留两位数字
if (bBig.compareTo(BigDecimal.ONE) > 0) {
return setScala(bBig, precision);
} else { // 小于0时,保留precision位有效数字
return bBig.round(new MathContext(precision, RoundingMode.HALF_UP));
}
}
return null;
}
public static BigDecimal setEffectiveNumber(Object b, boolean isCastInt) {
return setEffectiveNumber(b, DEFAULT_PRECISION, isCastInt);
}
/**
* 默认保留2位有效数字
*/
public static BigDecimal setEffectiveNumber(Object b, int precision) {
return setEffectiveNumber(b, precision, false);
}
public static BigDecimal setEffectiveNumber(Object b) {
return setEffectiveNumber(b, DEFAULT_PRECISION, false);
}
}