BigDecimal解决精度问题
前提
对于需要精确计算得场景和一些需要精确保留小数位的场景,可以使用BigDeciaml来做操作
举个例子,两数相乘或者相除:
double a = 1.235;
double b = 100.00;
System.out.println(a * b); // 期望结果:123.4
double c = 123.30;
double d = 100.00;
System.out.println(c / d); //期望结果:1.233
实际结果:
123.50000000000001
1.2329999999999999
使用BigDeciaml
BigDecimal a = new BigDecimal("1.235");
BigDecimal b = new BigDecimal("100.00");
BigDecimal c = new BigDecimal("123.30");
BigDecimal d = new BigDecimal("100.00");
System.out.println(a.multiply(b));
System.out.println(c.divide(d));
实际结果:
123.50000
1.233
构建
使用字符串来构造BigDecimal对象,如下
BigDecimal bd = new BigDecimal("0.1");
错误做法:
下面这种,使用double类型的参数构造BigDecimal,会有精度问题,不要使用
BigDecimal bd = new BigDecimal(0.1);
结果:
0.1000000000000000055511151231257827021181583404541015625
常用方法
- add(BigDecimal)
BigDecimal对象中的值相加,返回BigDecimal对象
- subtract(BigDecimal)
BigDecimal对象中的值相减,返回BigDecimal对象
- multiply(BigDecimal)
BigDecimal对象中的值相乘,返回BigDecimal对象
- divide(BigDecimal)
BigDecimal对象中的值相除,返回BigDecimal对象
- toString()
将BigDecimal对象中的值转换成字符串
- doubleValue()
将BigDecimal对象中的值转换成双精度数
- floatValue()
将BigDecimal对象中的值转换成单精度数
- longValue()
将BigDecimal对象中的值转换成长整数
- intValue()
将BigDecimal对象中的值转换成整数
- compareTo(BigDecimal val);
比较大小:-1小于;0相等;1大于
System.out.println(new BigDecimal("0.1").compareTo(new BigDecimal("0.2")));
System.out.println(new BigDecimal("0.2").compareTo(new BigDecimal("0.1")));
System.out.println(new BigDecimal("0.123").compareTo(new BigDecimal("0.123000000")));
结果:
-1
1
0
- BigDecimal setScale(int newScale, int roundingMode)
roundingMode:
public static final int ROUND_HALF_UP = 4; //向上取
public static final int ROUND_HALF_DOWN = 5; //向下取
.......
BigDecimal bigDecimal = new BigDecimal("0.12345678").setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(bigDecimal);
结果:
0.12
工具类
public class BigDecimalUtils {
/**
* 除法默认保留精度
*/
private static final int DEF_DIV_SCALE = 10;
/**
* 默认舍入模式(ROUND_HALF_UP:四舍五入)
*/
private static final int DEF_ROUNDING_MODE = BigDecimal.ROUND_HALF_UP;
private static final String FORMAT_1 = "#.##";
/**
* 将字符串转换为 BigDecimal
*
* @param value
* @return
*/
public static BigDecimal of(String value) {
return value == null ? null : new BigDecimal(value);
}
/**
* v1 + v2
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
return v1.add(v2);
}
/**
* args[0] + args[1] + ... + args[n]
*
* @param args
* @return
*/
public static BigDecimal add(BigDecimal... args) {
if (args == null || args.length <= 1) {
throw new IllegalArgumentException("args Contains at least two parameters");
}
BigDecimal result = args[0];
for (int i = 1; i < args.length; i++) {
result = add(result, args[i]);
}
return result;
}
/**
* v1 - v2
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static BigDecimal subtract(BigDecimal v1, BigDecimal v2) {
return v1.subtract(v2);
}
/**
* args[0] - args[1] - ... - args[n]
*
* @param args
* @return
*/
public static BigDecimal subtract(BigDecimal... args) {
if (args == null || args.length <= 1) {
throw new IllegalArgumentException("args Contains at least two parameters");
}
BigDecimal result = args[0];
for (int i = 1; i < args.length; i++) {
result = subtract(result, args[i]);
}
return result;
}
/**
* v1 * v2
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {
return v1.multiply(v2);
}
/**
* args[0] * args[1] * ... * args[n]
*
* @return 两个参数的积
*/
public static BigDecimal multiply(BigDecimal... args) {
if (args == null || args.length <= 1) {
throw new IllegalArgumentException("args Contains at least two parameters");
}
BigDecimal result = args[0];
for (int i = 1; i < args.length; i++) {
result = multiply(result, args[i]);
}
return result;
}
/**
* v1 / v2
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {
return v1.divide(v2, DEF_DIV_SCALE, DEF_ROUNDING_MODE);
}
/**
* args[0] / args[1] / ... / args[n]
*
* @return 两个参数的积
*/
public static BigDecimal divide(BigDecimal... args) {
if (args == null || args.length <= 1) {
throw new IllegalArgumentException("args Contains at least two parameters");
}
BigDecimal result = args[0];
for (int i = 1; i < args.length; i++) {
result = divide(result, args[i]);
}
return result;
}
/**
* 四舍五入,保留两位小数
*
* @param d
* @return
*/
public static BigDecimal round(BigDecimal d) {
if (d == null) {
return null;
}
return d.setScale(2, BigDecimal.ROUND_HALF_UP);
}
/**
* v1>v2?
*
* @param v1
* @param v2
* @return
*/
public static boolean gt(BigDecimal v1, BigDecimal v2) {
return v1.compareTo(v2) > 0;
}
/**
* v1 == v2
*
* @param v1
* @param v2
* @return
*/
public static boolean eq(BigDecimal v1, BigDecimal v2) {
return v1.compareTo(v2) == 0;
}
/**
* 判断 values 是否等于 0?
*
* @param value
* @return
*/
public static boolean eq0(BigDecimal value) {
return BigDecimal.ZERO.compareTo(value) == 0;
}
/**
* v1>=v2?
*
* @param v1
* @param v2
* @return
*/
public static boolean ge(BigDecimal v1, BigDecimal v2) {
return v1.compareTo(v2) >= 0;
}
/**
* v1<v2?
*
* @param v1
* @param v2
* @return
*/
public static boolean lt(BigDecimal v1, BigDecimal v2) {
return v1.compareTo(v2) < 0;
}
/**
* 格式化,保留2为小数
*
* @param value
* @return
*/
public static String format(BigDecimal value) {
if (value == null) {
return null;
}
DecimalFormat df = new DecimalFormat(FORMAT_1);
return df.format(value);
}
/**
* 格式化
*
* @param value
* @param pattern 模式字符串,如:#.##
* @return
*/
public static String format(BigDecimal value, String pattern) {
if (value == null) {
return null;
}
DecimalFormat df = new DecimalFormat(pattern);
return df.format(value);
}
}