Appearance
BigDecimal的使用
1、BigDecimal常用构造函数
- BigDecimal(int)
创建一个具有参数所指定整数值
的对象
- BigDecimal(double)
创建一个具有参数所指定双精度值
的对象
- BigDecimal(long)
创建一个具有参数所指定长整数值
的对象
- BigDecimal(String)
创建一个具有参数所指定以字符串表示的数值
的对象
2、使用的一些坑
java
BigDecimal a = new BigDecimal(0.1);
System.out.println("a的值:"+a);
System.out.println("=====================");
BigDecimal b = new BigDecimal("0.1");
System.out.println("b的值:"+b);
sh
a的值:0.1000000000000000055511151231257827021181583404541015625
=====================
b的值:0.1
3、BigDecimal常用方法
1、常用方法
add(BigDecimal)
BigDecimal对象中的值相加,返回BigDecimal对象
ubtract(BigDecimal)
BigDecimal对象中的值相减,返回BigDecimal对象
multiply(BigDecimal)
BigDecimal对象中的值相乘,返回BigDecimal对象
divide(BigDecimal)
BigDecimal对象中的值相除,返回BigDecimal对象
toString()
将BigDecimal对象中的值转换成字符串
doubleValue()
将BigDecimal对象中的值转换成双精度数
floatValue()
将BigDecimal对象中的值转换成单精度数
longValue()
将BigDecimal对象中的值转换成长整数
intValue()
将BigDecimal对象中的值转换成整数
2、BigDecimal大小比较
java中对BigDecimal比较大小一般用的是bigdemical的compareTo
方法
java
int a = bigdemical.compareTo(bigdemical2);
返回结果分析:
java
a = -1,表示bigdemical小于bigdemical2;
a = 0,表示bigdemical等于bigdemical2;
a = 1,表示bigdemical大于bigdemical2;
a大于等于b
java
new bigdemica(a).compareTo(new bigdemical(b)) >= 0
java
BigDecimal a =new BigDecimal("0.10");
BigDecimal b =new BigDecimal("0.1");
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.compareTo(b));
java
false
false
0
3、BigDecimal格式化
由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比。
java
NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立货币格式化引用
NumberFormat percent = NumberFormat.getPercentInstance(); //建立百分比格式化引用
percent.setMaximumFractionDigits(3); //百分比小数点最多3位
BigDecimal loanAmount = new BigDecimal("15000.48"); //贷款金额
BigDecimal interestRate = new BigDecimal("0.008"); //利率
BigDecimal interest = loanAmount.multiply(interestRate); //相乘
System.out.println("贷款金额:\t" + currency.format(loanAmount));
System.out.println("利率:\t" + percent.format(interestRate));
System.out.println("利息:\t" + currency.format(interest));
java
贷款金额: ¥15,000.48
利率: 0.8%
利息: ¥120.00
BigDecimal格式化保留2为小数,不足则补0:
java
package com.xx.bigdecimal;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* @Author: xueqimiao
* @Date: 2023/11/20 09:09
*/
public class BigDecimalTest {
public static void main(String[] args) {
System.out.println(formatToNumber(new BigDecimal("3.435")));
System.out.println(formatToNumber(new BigDecimal(0)));
System.out.println(formatToNumber(new BigDecimal("0.00")));
System.out.println(formatToNumber(new BigDecimal("0.001")));
System.out.println(formatToNumber(new BigDecimal("0.006")));
System.out.println(formatToNumber(new BigDecimal("0.206")));
}
public static String formatToNumber(BigDecimal obj) {
DecimalFormat df = new DecimalFormat("#0.00");
return df.format(obj).toString();
}
}
java
3.44
0.00
0.00
0.00
0.01
0.21
4、SpringBoot应用参数格式化
java
package com.xx.vo;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @Author: xueqimiao
* @Date: 2023/11/20 09:23
*/
@Data
public class BigDecimalVO implements Serializable {
private BigDecimal score;
private BigDecimal scoreTo;
}
java
@GetMapping("/testDecimal")
public ResultData test(){
BigDecimalVO bigDecimalVO = new BigDecimalVO();
bigDecimalVO.setScore(new BigDecimal("0"));
bigDecimalVO.setScoreTo(new BigDecimal("0"));
return new ResultData(bigDecimalVO);
}
@JsonSerialize
是 Java 中 Jackson 库提供的注解之一,用于定制对象在序列化(将对象转换为 JSON 字符串)过程中的行为。Jackson 是一个流行的 JSON 处理库,用于在 Java 对象和 JSON 数据之间进行转换。
当你在一个类或属性上使用 @JsonSerialize
注解时,你可以指定一个自定义的序列化器(serializer)。序列化器负责将对象转换为 JSON 格式,而不依赖于默认的方式。这可以用于处理一些特殊的需求,例如将对象以不同的方式序列化,或者在序列化过程中执行一些特殊的逻辑。
java
package com.xx.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* @Author: xueqimiao
* @Date: 2023/11/20 09:29
*/
public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {
@Override
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
gen.writeString(new DecimalFormat("#0.00").format(value));
}
}
}
java
@Data
public class BigDecimalVO implements Serializable {
private BigDecimal score;
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal scoreTo;
}
5、BigDecimal常见异常
java
public static void main(String[] args) {
BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal2 = new BigDecimal(3);
System.out.println(bigDecimal.divide(bigDecimal2));
}
java
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.base/java.math.BigDecimal.divide(BigDecimal.java:1780)
at com.xx.bigdecimal.BigDecimalTest.main(BigDecimalTest.java:15)
通过BigDecimal的divide方法进行除法时不整除,出现无限循环小数时,就会抛异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
java
public static void main(String[] args) {
BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal2 = new BigDecimal(3);
BigDecimal result = bigDecimal.divide(bigDecimal2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println(result);
}
2
表示2位小数,BigDecimal.ROUND_HALF_UP
是舍入模式,表示使用四舍五入。你可以根据你的需求选择不同的精度和舍入模式
4、BigDecimal工具类
java
package com.xx.util;
import com.xx.utils.ValidationUtil;
import java.math.BigDecimal;
/**
* @Author: xueqimiao
* @Date: 2023/11/20 10:15
*/
public class BigDecimalUtil {
/**
* 累加
*
* @param values
* @return
*/
public static BigDecimal add(BigDecimal... values) {
if (ValidationUtil.isEmpty(values) || values.length == 0) {
return new BigDecimal(0);
}
if (values.length == 1) {
return values[0];
} else {
BigDecimal returnNum = ValidationUtil.isEmpty(values[0]) ? new BigDecimal(0) : values[0];
for (int i = 1; i < values.length; i++) {
if (ValidationUtil.isEmpty(values[i])) {
continue;
}
BigDecimal b1 = returnNum;
BigDecimal b2 = values[i];
returnNum = b1.add(b2);
}
return returnNum;
}
}
/**
* 减法
*
* @param param
* @return
*/
public static BigDecimal subtract(BigDecimal... param) {
if (ValidationUtil.isEmpty(param) || param.length == 0) {
return new BigDecimal(0);
}
BigDecimal sumLess = param[0];//被减数
for (int i = 1; i < param.length; i++) {
BigDecimal bigDecimal = param[i] == null ? new BigDecimal(0) : param[i];
sumLess = sumLess.subtract(bigDecimal);
}
return sumLess;
}
/**
* 乘以
*
* @param v1
* @param v2
* @return
*/
public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {
if (ValidationUtil.isEmpty(v1) || ValidationUtil.isEmpty(v2)) {
return new BigDecimal(0);
}
BigDecimal multiply = v1.multiply(v2);
return multiply;
}
/**
* 除以
*
* @param v1
* @param v2
* @return
*/
public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {
if (ValidationUtil.isEmpty(v1) || ValidationUtil.isEmpty(v2) || v2.compareTo(new BigDecimal("0")) == 0) {
return new BigDecimal(0);
}
return v1.divide(v2, 3, BigDecimal.ROUND_HALF_DOWN);
}
/**
* 提供精确的减法运算
*
* @param v1 被减数
* @param v2 减数
* @param scale 保留scale 位小数
* @return 两个参数的差
*/
public static String sub(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留scale 位小数
* @return 两个参数的积
*/
public static double mul(double v1, double v2, int scale) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return round(b1.multiply(b2).doubleValue(), scale);
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留scale 位小数
* @return 两个参数的积
*/
public static String mul(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示需要精确到小数点以后几位
* @return 两个参数的商
*/
public static String div(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v1);
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(String v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(v);
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留几位
* @return 余数
*/
public static String remainder(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数 BigDecimal
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留几位
* @return 余数
*/
public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 比较大小
*
* @param v1 被比较数
* @param v2 比较数
* @return 如果v1 大于v2 则 返回true 否则false
*/
public static boolean compare(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
int bj = b1.compareTo(b2);
boolean res;
if (bj > 0)
res = true;
else
res = false;
return res;
}
}