刚学Java时我们会用float和double来做带小数的数值计算,但它俩只能用来做科学计算或者是工程计算(会有进度丢失问题)。如果对精度要求高,比如项目中计算金额、计算用水量用电量、计算住房面积时,我们需要使用Java在java.math包中提供的BigDecimal类。但BigDecimal是一个对象,不能像float和double直接进行加减乘除的计算,需要使用它提供的内置方法计算。
我在项目中写的一个操作BigDecimal的工具类:
package com.xxx.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
/**
* BigDecimal工具类
*
* 加法 add()
* 减法 subtract()
* 乘法 multiply()
* 除法 divide()
* 精度 setScale()
* 绝对值 abs()
*
* @Author wanglingqiang
* @Date 2021/9/15 14:39
*/
public class BigDecimalUtil {
private static final BigDecimal BigDecimal_ZERO = new BigDecimal("0.00");
/**
* 判断是否为空或0
*
* @param arg
* @return
*/
public static boolean isEmpty(BigDecimal arg) {
if (Objects.isNull(arg) || BigDecimal.ZERO.equals(arg) || BigDecimal_ZERO.equals(arg)) {
return true;
}
return false;
}
/**
* 乘法(精确小数点后2位、四舍五入)
*
* @param arg1
* @param arg2
* @return
*/
public static BigDecimal multiply(BigDecimal arg1, BigDecimal arg2) {
if (isEmpty(arg1) || isEmpty(arg2)) {
return BigDecimal.ZERO;
}
return arg1.multiply(arg2).setScale(2, RoundingMode.HALF_UP);
}
/**
* 除法(精确小数点后2位、四舍五入)
*
* @param arg1
* @param arg2
* @return
*/
public static BigDecimal divide(BigDecimal arg1, BigDecimal arg2) {
if (isEmpty(arg1) || isEmpty(arg2)) {
return BigDecimal.ZERO;
}
return BigDecimalUtil.divide(arg1, arg2, 2);
}
/**
* 除法(四舍五入)
*
* @param arg1
* @param arg2
* @param scale 精确几位数
* @return
*/
public static BigDecimal divide(BigDecimal arg1, BigDecimal arg2, int scale) {
if (isEmpty(arg1) || isEmpty(arg2)) {
return BigDecimal.ZERO;
}
return arg1.divide(arg2, scale, RoundingMode.HALF_UP);
}
/**
* 返回值,精确小数点后2位、四舍五入
*
* @param arg
* @return
*/
public static BigDecimal valueOf(BigDecimal arg) {
if (isEmpty(arg)) {
return BigDecimal.ZERO;
}
return arg.setScale(2, RoundingMode.HALF_UP);
}
/**
* 比较两个值的大小
* arg1 > arg2 返回1
* arg1 < arg2 返回-1
* arg1 == arg2 返回0
*
* @param arg1
* @param arg2
* @return
*/
public static int compare(BigDecimal arg1, BigDecimal arg2) {
if (isEmpty(arg1) || isEmpty(arg2)) {
throw new NullPointerException();
}
return arg1.compareTo(arg2);
}
private BigDecimalUtil() {
}
}
注意对BigDecimal做除法时,一定要设置精确的小数点。不然会报错Exception in thread “main” java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1693)
at com.crdigital.intelligent.park.modules.api.utils.ParkMapping.main(ParkMapping.java:104)
报错原因是不能整除,结果0.3333333……无限长。设置除法四舍五入且精确小数点后两位后,报错解决。
Java的BigDecimal类型在MySQL中对应的是decimal类型。比如:
CREATE TABLE `pay_record` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`pay_no` varchar(64) DEFAULT NULL COMMENT '支付编号',
`pay_user` varchar(64) DEFAULT NULL COMMENT '支付人',
`amount` decimal(18,2) DEFAULT '0.00' COMMENT '支付金额',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 1是 0否',
PRIMARY KEY (`id`)
) COMMENT='支付记录表'
本章完