文章目录
前言
最近项目中有一个需求。 需要累加库中某个字段的值,精确到小数点后两位,返回前端显示。 使用的第一件事就是实施它。 没想到出事了。 数据类型正在执行累加操作。 有时候会丢失精度,所以在显示数据的时候,输出的是小数点后很长的数据,所以果断改为运算,只是记录一些常用的操作。
一种类型
根据Java8中文手册,java.math包中Java提供的API类用于对16位有效数字以上的数字进行精确运算。 双精度浮点变量可以处理 16 位有效数。 在实际应用中,需要对更大或更小的数字进行计算和处理。 float只能用于科学计算或工程计算,而java.math用于商业计算。 创建的是一个对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相应的方法。 方法中的参数也必须是 的对象。 构造函数是类的一种特殊方法,旨在创建对象,尤其是带有参数的对象。
二、常用方法 1、施工方法
施工方法有四种。 声明类时,尽量不要直接传入值,因为构造是不可预测的。 建议使用.()传入
2. 基本算术和加法
使用add方法如下:
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.add(new BigDecimal(456)))
如果要添加的数字是一种数据,建议使用以下表示法:
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.add(new BigDecimal(String.valueOf(0.45))))
首先将数据转换为字符串,然后使用构造函数
如果执行加法后需要对结果进行四舍五入,可以执行以下操作:
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.add(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
减法
指示
BigDecimal num1 = new BigDecimal(456);
log.info("结果为:{}",num1.subtract(new BigDecimal(123)))
与上面相同的类型
也可以转圆
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.subtract(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
乘法
指示
BigDecimal num1 = new BigDecimal(456);
log.info("结果为:{}",num1.multiply(new BigDecimal(123)))
带加法的类型
也可以转圆
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.multiply(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
分配
指示
BigDecimal num1 = new BigDecimal(456);
log.info("结果为:{}",num1.divide(new BigDecimal(123)))
也可以转圆
BigDecimal num1 = new BigDecimal(123);
log.info("结果为:{}",num1.divide(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
3.保留小数(精确到几位)
可以使用该方法来处理一类有几位小数的数据
例如:
BigDecimal divisor = new BigDecimal(1000);
BigDecimal num = new BigDecimal(4561.2564);
num.divide(divisor, 2, BigDecimal.ROUND_CEILING)
log.info("原来的数除以1000保留两位小数:{}",num1.divide(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
或者只保留两位小数
BigDecimal num = new BigDecimal(4561.2564);
num.setScale(2, BigDecimal.ROUND_CEILING)
log.info("原来的数除以1000保留两位小数:{}",num1.divide(new BigDecimal(String.valueOf(0.45),BigDecimal.ROUND_CEILING)))
4. 舍入的类型
这里只记录了可能用到的几种类型
围捕
不管正负,只要大于
BigDecimal num = new BigDecimal(String.valueOf(1.4));
System.out.println(num.setScale(0, BigDecimal.ROUND_UP));
//2
BigDecimal num1 = new BigDecimal(String.valueOf(-1.4));
System.out.println(num1.setScale(0, BigDecimal.ROUND_UP));
//-2
向下舍入
无论正负,都会被丢弃
BigDecimal num = new BigDecimal(String.valueOf(1.4));
System.out.println(num.setScale(0, BigDecimal.ROUND_DOWN));
//1
BigDecimal num1 = new BigDecimal(String.valueOf(-1.4));
System.out.println(num1.setScale(0, BigDecimal.ROUND_DOWN));
//-1
向前舍入
是 的组合,如果为正,则行为相同,如果为负,则行为相同
BigDecimal num = new BigDecimal(String.valueOf(1.4));
System.out.println(num.setScale(0, BigDecimal.ROUND_CEILING));
//2
BigDecimal num1 = new BigDecimal(String.valueOf(-1.4));
System.out.println(num1.setScale(0, BigDecimal.ROUND_CEILING));
//-1
负舍入
and 的组合,但 and 是相反的。如果为正,则行为相同; 如果为负,则行为相同
BigDecimal num = new BigDecimal(String.valueOf(1.4));
System.out.println(num.setScale(0, BigDecimal.ROUND_FLOOR));
//1
BigDecimal num1 = new BigDecimal(String.valueOf(-1.4));
System.out.println(num1.setScale(0, BigDecimal.ROUND_FLOOR));
//-2
四舍五入
这是我们经常使用的,不再解释
BigDecimal num = new BigDecimal(String.valueOf(1.4));
System.out.println(num.setScale(0, BigDecimal.ROUND_HALF_UP));
//1
BigDecimal num1 = new BigDecimal(String.valueOf(-1.4));
System.out.println(num1.setScale(0, BigDecimal.ROUND_HALF_UP));
//-1
BigDecimal num2 = new BigDecimal(String.valueOf(1.5));
System.out.println(num2.setScale(0, BigDecimal.ROUND_HALF_UP));
//2
BigDecimal num3 = new BigDecimal(String.valueOf(-1.5));
System.out.println(num3.setScale(0, BigDecimal.ROUND_HALF_UP));
//-2
围捕
大于6则四舍五入,小于6则舍弃
BigDecimal num = new BigDecimal(String.valueOf(1.6));
System.out.println(num.setScale(0, BigDecimal.ROUND_HALF_DOWN));
//2
BigDecimal num1 = new BigDecimal(String.valueOf(-1.6));
System.out.println(num1.setScale(0, BigDecimal.ROUND_HALF_DOWN));
//-2
BigDecimal num2 = new BigDecimal(String.valueOf(1.5));
System.out.println(num2.setScale(0, BigDecimal.ROUND_HALF_DOWN));
//1
BigDecimal num3 = new BigDecimal(String.valueOf(-1.5));
System.out.println(num3.setScale(0, BigDecimal.ROUND_HALF_DOWN));
//-1
总结
在业务需求比较精准的情况下,避免基本数据类型带来的bug是非常有必要的