BigDecimal的使用
BigDecimal的使用
1、BigDecimal常用构造函数
- BigDecimal(int)
创建一个具有参数所指定整数值
的对象
- BigDecimal(double)
创建一个具有参数所指定双精度值
的对象
- BigDecimal(long)
创建一个具有参数所指定长整数值
的对象
- BigDecimal(String)
创建一个具有参数所指定以字符串表示的数值
的对象
2、使用的一些坑
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);
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
方法
int a = bigdemical.compareTo(bigdemical2);
返回结果分析:
a = -1,表示bigdemical小于bigdemical2;
a = 0,表示bigdemical等于bigdemical2;
a = 1,表示bigdemical大于bigdemical2;
a大于等于b
new bigdemica(a).compareTo(new bigdemical(b)) >= 0
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));
false
false
0
3、BigDecimal格式化
由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比。
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));
贷款金额: ¥15,000.48
利率: 0.8%
利息: ¥120.00
BigDecimal格式化保留2为小数,不足则补0:
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();}
}
3.44
0.00
0.00
0.00
0.01
0.21
4、SpringBoot应用参数格式化
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;
}
@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 格式,而不依赖于默认的方式。这可以用于处理一些特殊的需求,例如将对象以不同的方式序列化,或者在序列化过程中执行一些特殊的逻辑。
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> {@Overridepublic void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {if (value != null) {gen.writeString(new DecimalFormat("#0.00").format(value));}}
}
@Data
public class BigDecimalVO implements Serializable {private BigDecimal score;@JsonSerialize(using = BigDecimalSerializer.class)private BigDecimal scoreTo;
}
5、BigDecimal常见异常
public static void main(String[] args) {BigDecimal bigDecimal = new BigDecimal(1);BigDecimal bigDecimal2 = new BigDecimal(3);System.out.println(bigDecimal.divide(bigDecimal2));
}
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.
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工具类
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;elseres = false;return res;}
}