bigdecimal用错了,线上就会大问题了

金额计算相关的,很多用的就是bigdecimal吧,很多java的开发人员,在金额计算过程中,为了不失去精度,导致金额计算错误,通常都会使用这个属性,但是在使用的过程中,我发现了一个精度丢失的问题,在此记录一下

 

首先我们先看看具体问题复现:

public static void main(String[] args) {       BigDecimal bigDecimal=new BigDecimal(88);       System.out.println(bigDecimal);       bigDecimal=new BigDecimal("8.8");       System.out.println(bigDecimal);       bigDecimal=new BigDecimal(8.8);       System.out.println(bigDecimal);   }  

执行结果是这样的:

可以看到最后的bigdecimal(8.8)的结果是超出了8.8的范围,那在实际的计算过程中,肯定就会导致金额变大,数据不准确了

BigDecimal 在处理的时候把十进制小数扩大 N 倍让它在整数上进行计算,并保留相应的精度信息。

①float 和 double 类型,主要是为了科学计算和工程计算而设计的,之所以执行二进制浮点运算,是为了在广泛的数值范围上提供较为精确的快速近和计算。

②并没有提供完全精确的结果,所以不应该被用于精确的结果的场合。

③当浮点数达到一定大的数,就会自动使用科学计数法,这样的表示只是近似真实数而不等于真实数。

④当十进制小数位转换二进制的时候也会出现无限循环或者超过浮点数尾数的长度。

解决方法:

在实际开发过程中,int和string类型可以直接使用,不存在这个问题。但是遇到float和double类型的时候,就要转为string类型来进行计算即可。

BigDecimal bigDecimal2=new BigDecimal("8.8"); BigDecimal bigDecimal3=new BigDecimal("8.812"); System.out.println( bigDecimal2.compareTo(bigDecimal3)); System.out.println( bigDecimal2.add(bigDecimal3));

再给大家分享一个工具来进行bigdecimal的计算:

import java.math.BigDecimal; /** * @Author shuaige * @Date 2022/4/17 * @Version 1.0 **/ public class BigDecimalUtils {     public static BigDecimal doubleAdd(double v1, double v2) {         BigDecimal b1 = new BigDecimal(Double.toString(v1));         BigDecimal b2 = new BigDecimal(Double.toString(v2));         return b1.add(b2);     }     public static BigDecimal floatAdd(float v1, float v2) {         BigDecimal b1 = new BigDecimal(Float.toString(v1));         BigDecimal b2 = new BigDecimal(Float.toString(v2));         return b1.add(b2);     }     public static BigDecimal doubleSub(double v1, double v2) {         BigDecimal b1 = new BigDecimal(Double.toString(v1));         BigDecimal b2 = new BigDecimal(Double.toString(v2));         return b1.subtract(b2);     }     public static BigDecimal floatSub(float v1, float v2) {         BigDecimal b1 = new BigDecimal(Float.toString(v1));         BigDecimal b2 = new BigDecimal(Float.toString(v2));         return b1.subtract(b2);     }     public static BigDecimal doubleMul(double v1, double v2) {         BigDecimal b1 = new BigDecimal(Double.toString(v1));         BigDecimal b2 = new BigDecimal(Double.toString(v2));         return b1.multiply(b2);     }     public static BigDecimal floatMul(float v1, float v2) {         BigDecimal b1 = new BigDecimal(Float.toString(v1));         BigDecimal b2 = new BigDecimal(Float.toString(v2));         return b1.multiply(b2);     }     public static BigDecimal doubleDiv(double v1, double v2) {         BigDecimal b1 = new BigDecimal(Double.toString(v1));         BigDecimal b2 = new BigDecimal(Double.toString(v2));         // 保留小数点后两位 ROUND_HALF_UP = 四舍五入         return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);     }     public static BigDecimal floatDiv(float v1, float v2) {         BigDecimal b1 = new BigDecimal(Float.toString(v1));         BigDecimal b2 = new BigDecimal(Float.toString(v2));         // 保留小数点后两位 ROUND_HALF_UP = 四舍五入         return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);     }     /**     * 比较v1 v2大小     * @param v1     * @param v2     * @return v1>v2 return 1  v1=v2 return 0 v1<v2 return -1     */     public static int doubleCompareTo(double v1, double v2) {         BigDecimal b1 = new BigDecimal(Double.toString(v1));         BigDecimal b2 = new BigDecimal(Double.toString(v2));         return  b1.compareTo(b2);     }     public static int floatCompareTo(float v1, float v2) {         BigDecimal b1 = new BigDecimal(Float.toString(v1));         BigDecimal b2 = new BigDecimal(Float.toString(v2));         return  b1.compareTo(b2);     } }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ai飞仔小密圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值