Double数据类型精度丢失

在处理金融业务时,发现使用Double计算金额导致精度丢失。为解决此问题,文章介绍了如何利用BigDecimal的valueOf方法将Double转换为高精度的BigDecimal对象,并利用其内置的数值计算方法,如subtract和add,配合指定精度策略(如四舍五入),确保计算精确到小数点后特定位数。注意,不同页面的数据展示差异可能导致结果不同,但这并不一定是由于精度问题引起的。

在这行业务逻辑代码中用Double来统计金额

 

展示到页面时发现精度丢失 

 使用BigDecimal封装的方法valueOf 转化为BigDecimal类型数据

BigDecimal中封装了很多数值计算的方法

如num1.subtract(num2,mc)相当于num1-mum2 mc是设置的精度可以调策略 比如四舍五入 可以看底层原码 有很多

num1.add(num2,mc) 相当于num1+num2

 这里回复到小数点后2位

前后我使用的数据页面不同 导致结果不同 不是因为精度丢失导致的差距这么大这个要注意

### 精度丢失的原因 在计算机中,数据是以二进制形式存储和处理的。double 类型是一种双精度浮点数,遵循 IEEE 754 标准。然而,许多十进制小数无法精确地表示为二进制小数,这就导致了精度丢失。例如,0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。当使用 `new BigDecimal(0.1)` 时,实际上得到的是 0.1000000000000000055511151231257827021181583404541015625,这表明传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)[^4]。 ### 解决方法 #### 使用 BigDecimal 类 - **使用 String 构造方法**:String 构造方法是完全可预知的,写入 `new BigDecimal("0.1")` 将创建一个 BigDecimal,它正好等于预期的 0.1。通常建议优先使用 String 构造方法。示例代码如下: ```java import java.math.BigDecimal; public class DoubleCalculation { public static void main(String[] args) { BigDecimal num1 = new BigDecimal("0.1"); BigDecimal num2 = new BigDecimal("0.2"); BigDecimal result = num1.add(num2); System.out.println(result); } } ``` - **使用 `BigDecimal.valueOf(double d)` 方法**:当 double 必须用作 BigDecimal 的源时,`BigDecimal.valueOf(double d)` 方法提供了一个准确转换。示例代码如下: ```java import java.math.BigDecimal; public class DoubleCalculationValueOf { public static void main(String[] args) { double num1 = 0.1; double num2 = 0.2; BigDecimal bd1 = BigDecimal.valueOf(num1); BigDecimal bd2 = BigDecimal.valueOf(num2); BigDecimal result = bd1.add(bd2); System.out.println(result); } } ``` #### 自定义方法 可以编写一个自定义方法,将 double 类型转换为 String 类型,再使用 BigDecimal 进行计算。示例代码如下: ```java import java.math.BigDecimal; public class DoubleFormatAdd { public static Double doubleFormatAdd(Double... doubles) { BigDecimal count = new BigDecimal("0"); for (Double aDouble : doubles) { BigDecimal bigDecimal = new BigDecimal(aDouble.toString()); count = count.add(bigDecimal); } return count.doubleValue(); } public static void main(String[] args) { Double num1 = 1.0; Double num2 = 0.2; Double result = doubleFormatAdd(num1, num2); System.out.println(result); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值