BigDecimal的使用方法和注意事项

文章目录

  • BigDecimal的使用方法和注意事项
    • 1.构造方法
    • 2.加减乘除(绝对值)
    • 3.注意事项

做超市管理系统纯后端用的JDBC然后数据库里面的金额字段是BigDecimal的

做的时候遇到了好多坑,总结下来希望和我一样的萌新看到少走弯路

float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。但是,商业计算往往要求结果精确,这时候BigDecimal就派上大用场啦。

探讨一:java已经有基本的数据类型float和double了为什么还要用DigDecimal呢接下来我们看一个案例

        System.out.println(0.1 + 0.2);     //0.30000000000000004System.out.println(0.3 - 0.1);     //0.19999999999999998System.out.println(0.1 * 0.2);     //0.020000000000000004System.out.println(0.3 / 0.2);     //1.4999999999999998
--------------------------------------------------------------------------------
--------------------------------------对比---------------------------------------
--------------------------------------------------------------------------------BigDecimal big1 = new BigDecimal("0.3");    System.out.println(big1);BigDecimal big2 = new BigDecimal("0.2");System.out.println(big1.divide(big2));       //1.5

看一下0.3/0.2的结果通过基本类型计算得出来的是1.4999999999999998一个近似值而BigDecimal是一个准确的数值所以在进行金钱计算的时候一定要用准确是数字BigDcimal的作用就体现出来了

探讨二:在小数操作中,我们通常希望能有多种自由的定义方式。例如在不同的场景可能需要返回: 0.3, 0.4, 0.334等不同精度,在不同的精度进位时希望能自主控制。这个时候BigDecimal也可以帮忙

 情况一   double a = 3;double b = 10;double c = b / a;         //3.3333333333333335System.out.println(c);   //大家都知道3/10的结果是一个无线循环小数,怎么擦能拿到结果0.334呢
--------------------------------------------------------------------------------解决方法  BigDecimal big1 = new BigDecimal("10");BigDecimal big2 = new BigDecimal("3");BigDecimal result = big1.divide(big2,3,BigDecimal.ROUND_UP);//制定精度System.out.println(result);
--------------------------------------------------------------------------------    情况二  BigDecimal a = new BigDecimal(5.4);BigDecimal b = new BigDecimal(3.1);BigDecimal divide = a.divide(b);System.out.println("divide:" + divide);  // 出现异常:
//`ava.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
//这个错误是因为没有指定精度导致的,我们只要指定了结果的精度,就可以避免这个问题。
--------------------------------------------------------------------------------
解决方法  BigDecimal d = new BigDecimal(5.4);BigDecimal f = new BigDecimal(3.1);BigDecimal divide = d.divide(f,2,BigDecimal.ROUND_UP);//制定精度System.out.println("divide:" + divide);                 //1.74

我们额外传入第二个参数:保留的小数,指定了结果的精度,就可以避免出现这种问题。

所以我们日常用BigDecimal做除法运算的时候,务必写成推荐的形式。避免出现了异常。

1.构造方法

构造 描述
BigDecimal(double val) double转换为 BigDecimal ,这是 double的二进制浮点值的精确十进制表示
BigDecimal(int val) intBigDecimal
BigDecimal(String val) 将BigDecimal的字符串表示 BigDecimal转换为 BigDecimal
         BigDecimal bigdouble = new BigDecimal(5.4);    //5.4000000000000003552713678800500929355621337890625BigDecimal bigInt = new BigDecimal(3);           //3BigDecimal bigString = new BigDecimal("3.2");  //3.2

不知道大家有没有看出什么端倪通过参数是double构造方法生成的bigdouble的数值我们不太认识。为什么会出现这种状况呢?

JDK的描述

1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。

当double必须用作BigDecimal的源时,请使用Double.toString(double)转成String,然后使用BigDecimal的参数为String类型的构造方法,或使用BigDecimal的静态方法valueOf,如下

        BigDecimal bDouble1 = BigDecimal.valueOf(5.4);                //2.3BigDecimal bDouble2 = new BigDecimal(Double.toString(5.4));   //2.3    

2.加减乘除(绝对值)

     BigDecimal big1 = new BigDecimal("5");BigDecimal big2 = new BigDecimal("40");BigDecimal big3 = new BigDecimal("-20");//加法BigDecimal add = big1.add(big2);//减法BigDecimal subtract = big1.subtract(big2);//乘法BigDecimal multiply = big1.multiply(big2);//除法BigDecimal divide = big1.divide(big2);//绝对值BigDecimal abs  = big3.abs();System.out.println("  add    :" + add);             //45System.out.println("subtract :" + subtract);       //-35      System.out.println("multiply :" + multiply);      //200System.out.println(" divide  :" + divide);          //0.125System.out.println("  abs    :"+abs);                 //20

3.注意事项

1)System.out.println()中的数字默认是double类型的,double类型小数计算不精准。

2)使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!

  1. BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。

4)使用除法函数在divide的时候要设置各种参数,要精确的小数位数和舍入模式,不然会出现报错

我们可以看到divide函数配置的参数如下

  • divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
  • 返回一个 BigDecimal ,其值为 (this / divisor) ,其比例为指定。
即为 (BigDecimal divisor 除数, int scale 精确小数位,  int roundingMode 舍入模式)

可以看到舍入模式有很多种BigDecimal.ROUND_XXXX_XXX, 具体都是什么意思呢

模式 描述
CEILING 正无穷大方向取整
FLOOR 负无穷大方向取整
DOWN 向 0 的方向取整
UP 正数向正无穷大取整,负数向负无穷大取整(常用)
HALF_UP 5,6,7,8,9 向上取整、 1,2,3,4 向下取整、 常用的4舍5入
HALF_DOWN 6,7,8,9 向上取整 1,2,3,4,5 向下取整
HALF_EVEN 小数位是5时,判断整数部分是奇数就进位、 小数位是5时,判断整数部分是偶数就舍弃、 1,2,3,4, 舍弃、 6,7,8,9, 进位

BigDecimal的使用方法和注意事项相关推荐

  1. Dubbo+zookeeper使用方法以及注意事项

    Dubbo+zookeeper使用方法以及注意事项 最近在一个项目中想做一个数据库查询的服务,目的是将数据库查询这块从程序中脱离出来,形成一个公共的服务平台,大家都可以调用,经过考虑决定选用Dubbo ...

  2. 为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! BigDecimal,相信对于很多人来说都不陌生,很多人都 ...

  3. 【PC工具】200412更新百度网盘下载工具——最终最简单百度网盘下载方法及注意事项...

    今天有朋友在群里问会员账号,上次好像说过,这种公用的会员账号基本下载量都超了,同样也限速,所以这种账号一般都用来找资源. 百度网盘这个题材也来回来去发过好几个工具了,太麻烦不说,老这么道高一尺魔高一丈 ...

  4. 【PC工具】200324更新百度网盘下载工具——最新百度网盘下载工具使用方法及注意事项...

    今天(200324)更新一个大牛的个人项目pdown,大家可以收藏一下备用(为啥是备用呢,细心的小伙伴应该发现我把标题中的高速两个字去掉了). 先发项目地址:没错还是那个神奇的网站(大神奇人聚集的地方 ...

  5. 【PC工具】更新百度网盘高速下载工具——亿寻使用方法及注意事项

    之前分享的工具和方法大部分都不好用了,我也就不保留了,有需要的朋友可以翻看之前的历史文章. 今天分享一个目前比较主流的下载工具"亿寻",可能很多朋友都用过了,这里我简单说一下使用方 ...

  6. php获取表单$_files,PHP中$_FILES的使用方法及注意事项说明

    $_FILES:经由 HTTP POST 文件上传而提交至脚本的变量,类似于旧数组$HTTP_POST_FILES 数组(依然有效,但反对使用)详细信息可参阅 POST方法上传 $_FILES数组内容 ...

  7. 佳能g3800故障灯说明书_汽车仪表灯的使用方法以及注意事项

    能够准确地识别仪表盘上的数据是每个驾驶员的必要能力,但是如今,汽车技术日新月异,大量先进技术已应用于我们的爱车上.汽车仪表盘上的指示灯和中控台上的指示灯按钮变得越来越繁杂,准确识别这些抽象按钮已不再是 ...

  8. BigDecimal类setScale方法问题:算数异常,精确度丢失-ArithmeticException: Rounding necessary

    BigDecimal类setScale方法问题:算数异常,精确度丢失-ArithmeticException: Rounding necessary 在运行如下代码时, package BigDeci ...

  9. 电脑安全注意事项_松下洗衣机维修方法及注意事项

    阅读本文前,请您先点击上面的"蓝色字体",再点击"关注",这样您就可以继续免费收到文章了.每天都有分享,完全是免费订阅,请放心关注. 注:本文转载自网络,不代表 ...

  10. go面向对象编程:结构体struct详解、结构体实例的创建方式、结构体之间的转换(type取别名的使用)、方法的注意事项及与函数的区别

    入门示例 package main import "fmt" //定义老师结构体,将老师中的各个属性 统一放入结构体中管理: type Teacher struct{//变量名字大 ...

最新文章

  1. html代码转换成为纯文本
  2. python外星人入侵游戏代码_Python游戏:外星人入侵游戏编程完整版!内附代码
  3. CentOS7安装配置redis5.0.5
  4. 安卓手机玩游戏卡顿怎么解决_手机卡顿怎么办?教你3个实用解决方法,两分钟解决卡顿难题!...
  5. css中改变边距会影响原大小,CSS:更改父容器中子项的边距会改变子项的宽度吗?...
  6. linux 第三章红帽子,红帽子 Linux_命令全解
  7. java对mysql的简单操作——增加数据
  8. 第四季 word vba
  9. Nginx核心原理揭秘:Nginx为什么高效?
  10. 安卓版 网易云音乐 6.4.3
  11. PS中标尺工具在哪里
  12. React 父组件获取子组件的方法/数据(useRef
  13. 邮储社招Java笔试题_2019年及历年中国邮政储蓄银行社招笔试题和参考答案6套
  14. Debugging RJS
  15. 虚拟主机服务器放在哪里,云虚拟主机的目录在哪里
  16. 【干货】java课程实战培训
  17. jquery-weui扩展功能Picker实现营业时间选择
  18. iOS原生二维码扫描(一)
  19. 高质量C++/C 编程指南
  20. HDFS Truncate文件截断

热门文章

  1. Python开发过程中错误解决记录【持续更新记录,欢迎交流】
  2. 基于face_recognition构建的人脸识别系统以及相关应用
  3. Python绘制散点对比图
  4. 2021-08-04 Mysql联表查询
  5. 如何通过ip访问服务器文件共享,通过ip访问云服务器文件共享
  6. 计算机组成原理2套题,计算机组成原理试卷2套含答案(大学期末复习资料).doc...
  7. python开发怎么成长_Python开发者四大进阶攻略,菜鸟的成神之路
  8. DevOps技术学习路线图 初阶+中阶+高阶
  9. FISCO BCOS 同态加密 实例
  10. linux .o,.a,.so文件区别是什么