Java使用BigDecimal公式精确计算及精度丢失问题

 更新时间:2023年01月30日 08:52:02   作者:你才是臭弟弟  
在工作中经常会遇到数值精度问题,比如说使用float或者double的时候,可能会有精度丢失问题,下面这篇文章主要给大家介绍了关于Java使用BigDecimal公式精确计算及精度丢失问题的相关资料,需要的朋友可以参考下

一、Java使用BigDecimal公式计算(精确计算)

介绍:

       使用BigDecimal加减乘除方法运算,可以使用BigDecimal类提供的add、subtract、multiply、divide方法函数实现。

公式加法计算~add

  public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
 
       BigDecimal b = BigDecimal.valueOf(2.1);
 
       //BigDecimal计算add
       BigDecimal addResult = a.add(b);
       System.out.println("结果集: " +addResult);
   }

结果集: 

公式减法计算~subtract

public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
 
       BigDecimal b = BigDecimal.valueOf(2.1);
 
       BigDecimal计算subtract
       BigDecimal subtract = a.subtract(b);
 
       System.out.println("结果集subtract: " +subtract);
   }

结果集:

公式乘法计算~multiply

public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
       BigDecimal b = BigDecimal.valueOf(2.1);
       BigDecimal计算multiply
       BigDecimal multiply = a.multiply(b);
       System.out.println("结果集: " +multiply);
   }

结果集:

公式除法计算~divide

public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
       BigDecimal b = BigDecimal.valueOf(2.1);
       //BigDecimal计算divide
       //ROUND_HALF_UP:向“最接近的”整数舍入。 若舍入位大于等于5,则对舍入部分的前一位数字加1;若舍入位小于5,则直接舍弃。即为四舍五入模式。
       BigDecimal divide = a.divide(b,2,BigDecimal.ROUND_HALF_UP);//四舍五入,保留两位小数.
 
       System.out.println("结果集: " +divide);
   }

结果集:

二、 BigDecimal(舍入模式)选择

简介:

BigDecimal.setScale主要用于对BigDecimal数据小数点后的位数进行 进位、舍位、截断等操作

java.math.RoundingMode:这是一种枚举类型,它定义了8种数据的舍入模式。它与java.math.BigDecimal类中定义的8个同名静态常量的作用相同,可用BigDecimal.setScale(int newScale, RoundingMode roundingMode)来设置数据的精度和舍入模式。
 

1、ROUND_UP:向远离零的方向舍入。

        若舍入位为非零,则对舍入部分的前一位数字加1;若舍入位为零,则直接舍弃。即为向外取整模式。

2、ROUND_DOWN:向接近零的方向舍入。

        不论舍入位是否为零,都直接舍弃。即为向内取整模式。

3、ROUND_CEILING:向正无穷大的方向舍入。

        若 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;若为负,则舍入行为与 ROUND_DOWN 相同。即为向上取整模式。

4、ROUND_FLOOR:向负无穷大的方向舍入。

        若 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;若为负,则舍入行为与 ROUND_UP 相同。即为向下取整模式。

5、ROUND_HALF_UP:向“最接近的”整数舍入。

        若舍入位大于等于5,则对舍入部分的前一位数字加1;若舍入位小于5,则直接舍弃。即为四舍五入模式。

6、ROUND_HALF_DOWN:向“最接近的”整数舍入。

        若舍入位大于5,则对舍入部分的前一位数字加1;若舍入位小于等于5,则直接舍弃。即为五舍六入模式。

7、ROUND_HALF_EVEN:向“最接近的”整数舍入。

        若(舍入位大于5)或者(舍入位等于5且前一位为奇数),则对舍入部分的前一位数字加1;

        若(舍入位小于5)或者(舍入位等于5且前一位为偶数),则直接舍弃。即为银行家舍入模式。

8、ROUND_UNNECESSARY

        断言请求的操作具有精确的结果,因此不需要舍入。

        如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

案例: 

 public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
       BigDecimal b = BigDecimal.valueOf(2.1);
       //BigDecimal计算divide
       //ROUND_HALF_UP:向“最接近的”整数舍入。 若舍入位大于等于5,则对舍入部分的前一位数字加1;若舍入位小于5,则直接舍弃。即为四舍五入模式。
       //ROUND_UP:向远离零的方向舍入。  若舍入位为非零,则对舍入部分的前一位数字加1;若舍入位为零,则直接舍弃。即为向外取整模式。
       BigDecimal divide = a.divide(b,BigDecimal.ROUND_HALF_UP, 2).setScale(2,ROUND_UP);
 
       System.out.println("结果集: " +divide);
   }

结果集:

计算器结果集如下图:

三、 BigDecimal.setScale用法案例

BigDecimal.setScale主要用于对BigDecimal数据小数点后的位数进行 进位、舍位、截断等操作

public  static void main(String[] args){
       BigDecimal a = BigDecimal.valueOf(5.6);
       BigDecimal b = BigDecimal.valueOf(2.1);
       //BigDecimal计算divide
       BigDecimal divide = a.divide(b,2,BigDecimal.ROUND_UP).setScale(2, BigDecimal.ROUND_UP);
 
       System.out.println("结果集: " +divide);
   }

结果集:

四、Java使用BigDecimal精度丢失问题

介绍:

在实际应用中,经常会使用到计算,举例如 '银行' 特别是在我们交易的时候,计算结果要求的更加精确,这个时候我们就会使用到java.math包中提供的API类BigDecimal,用于对超过16位有效位数的数字进行精确的计算。

以如下代码为例:

public  static void main(String[] args){
       System.out.println("使用bigDecimal进行转换"+new BigDecimal(234.567));
   }

运行后结果集出现精度丢失: 

结果可以看出使用new BigDecimal(234.567),传入参数为double类型发生精度丢失,运行的结果并不等于234.567,而是为234.5670000000000072759576141834259033203125。

原因是double不能表示为任何有限长度的二进制小数;

解决方法:     使用new BigDecimal(String)构造函数,创建一个参数以字符串表示数值的对象

public  static void main(String[] args){
       double a = 234.567;
       String  b = "234.567";
       // 方式一:double的封装类Double中的toString()方法解决
       System.out.println("使用bigDecimal进行转换" + new BigDecimal(new Double(a).toString()));
 
       // 方式二:使用String接收数值
       System.out.println("使用bigDecimal进行转换" + new BigDecimal(b));
   }

 结果集如下:

如需使用加减乘除方法运算,可以使用BigDecimal类提供的add、subtract、multiply、divide方法实现 如上:Java使用BigDecimal公式计算

总结

到此这篇关于Java使用BigDecimal公式精确计算及精度丢失问题的文章就介绍到这了,更多相关Java使用BigDecimal公式精确计算内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8 CompletableFuture详解

    Java8 CompletableFuture详解

    这篇文章主要介绍了Java8 CompletableFuture详解,CompletableFuture extends Future提供了方法,一元操作符和促进异步性以及事件驱动编程模型,需要的朋友可以参考下
    2014-06-06
  • Postman实现传List<String>集合

    Postman实现传List<String>集合

    这篇文章主要介绍了Postman实现传List<String>集合方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java多线程 乐观锁和CAS机制详细

    Java多线程 乐观锁和CAS机制详细

    这篇文章主要介绍了Java多线程 乐观锁和CAS机制,乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁,需要的朋友可以参考下
    2021-10-10
  • Map如何根据key指定条件进行过滤筛选

    Map如何根据key指定条件进行过滤筛选

    这篇文章主要介绍了Map如何根据key指定条件进行过滤筛选问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java返回可变引用对象问题整理

    Java返回可变引用对象问题整理

    在本篇文章里小编给大家分享的是关于Java返回可变引用对象问题整理内容,需要的朋友们可以学习下。
    2020-04-04
  • Java使用协同过滤算法的代码示例

    Java使用协同过滤算法的代码示例

    在Java中实现协同过滤算法通常需要一些步骤,包括加载用户-项目评分数据、计算相似度、生成推荐等,以下是一个简化的基于用户的协同过滤算法的代码示例,感兴趣的小伙伴跟着小编一起来看看吧
    2024-06-06
  • Java动态代理分析及简单实例

    Java动态代理分析及简单实例

    这篇文章主要介绍了 Java动态代理分析及简单实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • Java的CollectionUtils工具类详解

    Java的CollectionUtils工具类详解

    这篇文章主要介绍了Java的CollectionUtils工具类详解,CollectionUtils工具类是在apache下的,而不是springframework下的,个人觉得在真实项目中CollectionUtils,可以使你的代码更加简洁和安全,需要的朋友可以参考下
    2023-05-05
  • java类成员中的访问级别浅析

    java类成员中的访问级别浅析

    在本篇文章里小编给大家整理的是一篇关于java类成员中的访问级别浅析内容,有兴趣的朋友们跟着学习下。
    2021-01-01
  • Redis实现商品秒杀功能页面流程

    Redis实现商品秒杀功能页面流程

    这篇文章主要介绍了Redis实现商品秒杀功能的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09

最新评论