处理金钱的BigDecimal
double和flaot在计算时会有精度的丢失,因此在需要精确计算时,使用BigDecimal。
一,float与doble处理金钱有误差
float:m1 = 0.1
float:m2 = 9.0
double:n1 = 0.03
double:n2 = 0.02
float:m1 * m2 : 0.90000004
double:n1-n2 : 0.009999999999999998
二,BigDecimal处理金钱没有误差
部分代码:
BigDecimal m3 =new BigDecimal("0.1");
System.out.println("BigDecimal:m3 = " +m3);
BigDecimal m4 =new BigDecimal("9.0");
System.out.println("BigDecimal:m4 = " +m4);
//乘法
System.out.println("BigDecimal:m3 * m4 : " +m3.multiply(m4));
//除法
System.out.println("BigDecimal:m3 / m4 : " +m4.divide(m3));
//加法
System.out.println("BigDecimal:m3 + m4 : " +m4.add(m3));
//减法
System.out.println("BigDecimal:m3 — m4 : " +m4.subtract(m3));
// 比较取最大值
m3.max(m4);
System.out.println("BigDecimal:m3 — m4 : " +m3.max(m4));
// 比较取最小值
m3.min(m4);
System.out.println("BigDecimal:m3 — m4 : " +m3.min(m4));
// 取绝对值
m3.abs();
System.out.println("BigDecimal:m3 — m4 : " +m3.abs());
// 取相反数
m3.negate();
System.out.println("BigDecimal:m3 — m4 : " +m3.negate());
结果:
BigDecimal:m3 = 0.1
BigDecimal:m4 = 9.0
BigDecimal:m3 * m4 : 0.90
BigDecimal:m3 / m4 : 90
BigDecimal:m3 + m4 : 9.1
BigDecimal:m3 — m4 : 8.9
BigDecimal:m3 — m4 : 9.0
BigDecimal:m3 — m4 : 0.1
BigDecimal:m3 — m4 : 0.1
BigDecimal:m3 — m4 : -0.1
三,BigDecimal处理金钱比较大小以及判空
1.equals:判断俩个BigDecimal是否相等会考虑值和精度(一般不用)
2.compareTo:忽略精度比较俩个数字是否相等。(举荐)
部分代码:
BigDecimal num = new BigDecimal("-8");
switch (num.compareTo(BigDecimal.ZERO)) {
case -1:
System.out.println("num小于0");
break;
case 1:
System.out.println("num大于0");
break;
case 0:
System.out.println("num等于0");
break;
}
结果:
num小于0
两个BigDecimal值⽐较使⽤compareTo⽅法, ⽐较结果有-1, 0, 1, 分别表⽰⼩于, 等于, ⼤于; 对于0, 可以使⽤BigDecimal.ZERO表⽰
四,BigDecimal处理金钱,⼩数位数四舍五⼊规则
方法一:最简便的方法,调用DecimalFormat类
22.27
方法二:直接通过String类的format函数实现
22.27
方法三:通过BigDecimal类实现
22.26
jdk9方法过期。现在的方法只能传入大于目前小数位数的值
b1 = 22.2656670
round 方法22.3
plus方法22.3
方法四:通过NumberFormat类实现
22.266
注意:String类的format函数的学习可参考https://blog.csdn.net/yunzhonghefei/article/details/112002896
BigDecimal的5种进位方式
jdk8使用方式
BigDecimal b1 = new BigDecimal("22.265667000");
System.out.println( b1.setScale(2, BigDecimal.ROUND_DOWN));//22.27
jdk9使用方式
BigDecimal b1 = new BigDecimal("22.265667000");
System.out.println(b1.setScale(2,RoundingMode.UP));//22.26
五,Hutool数字工具处理BigDecimal
加减乘除
NumberUtil.add针对数字类型做加法
NumberUtil.sub针对数字类型做减法
NumberUtil.mul针对数字类型做乘法
NumberUtil.div针对数字类型做除法,并提供重载方法用于规定除不尽的情况下保留小数位数和舍弃方式。
以上四种运算都会将double转为BigDecimal后计算,解决float和double类型无法进行精确计算的问题。这些方法常用于商业计算。
保留小数
保留小数的方法主要有两种:
NumberUtil.round方法主要封装BigDecimal中的方法来保留小数,返回BigDecimal,这个方法更加灵活,可以选择四舍五入或者全部舍弃等模式。
double te1=123456.123456;
double te2=123456.128456;
Console.log(round(te1,4));//结果:123456.1235
Console.log(round(te2,4));//结果:123456.1285
NumberUtil.roundStr方法主要封装String.format方法,舍弃方式采用四舍五入。
double te1=123456.123456;
double te2=123456.128456;
Console.log(roundStr(te1,2));//结果:123456.12
Console.log(roundStr(te2,2));//结果:123456.13
decimalFormat
针对DecimalFormat.format进行简单封装。按照固定格式对double或long类型的数字做格式化操作。
long c=299792458;//光速
String format = NumberUtil.decimalFormat(",###", c);//299,792,458
格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。
0 -> 取一位整数
0.00 -> 取一位整数和两位小数
00.000 -> 取两位整数和三位小数
# -> 取所有整数部分
#.##% -> 以百分比方式计数,并取两位小数
#.#####E0 -> 显示为科学计数法,并取五位小数
,### -> 每三位以逗号进行分隔,例如:299,792,458
光速大小为每秒,###米 -> 将格式嵌入文本
关于格式的更多说明,请参阅:Java DecimalFormat的主要功能及使用方法
是否为数字
NumberUtil.isNumber是否为数字
NumberUtil.isInteger是否为整数
NumberUtil.isDouble是否为浮点数
NumberUtil.isPrimes是否为质数
随机数
NumberUtil.generateRandomNumber生成不重复随机数 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的数组。
NumberUtil.generateBySet生成不重复随机数 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的数组。
整数列表
NumberUtil.range方法根据范围和步进,生成一个有序整数列表。NumberUtil.appendRange将给定范围内的整数添加到已有集合中
其它
NumberUtil.factorial阶乘
NumberUtil.sqrt平方根
NumberUtil.divisor最大公约数
NumberUtil.multiple最小公倍数
NumberUtil.getBinaryStr获得数字对应的二进制字符串
NumberUtil.binaryToInt二进制转int
NumberUtil.binaryToLong二进制转long
NumberUtil.compare比较两个值的大小
NumberUtil.toStr数字转字符串,自动并去除尾小数点儿后多余的0
来自糊涂官网:https://www.hutool.cn/docs/#/core/%E5%B7%A5%E5%85%B7%E7%B1%BB/%E6%95%B0%E5%AD%97%E5%B7%A5%E5%85%B7-NumberUtil?id=decimalformat
以上全部学习代码请点这里下载(为省空间,请自行新建测试项目)