BigDecimal的使用方法和注意事项
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)
|
将 int 成 BigDecimal
|
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类型时,计算的结果也是不精确的!
- 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的使用方法和注意事项相关推荐
- Dubbo+zookeeper使用方法以及注意事项
Dubbo+zookeeper使用方法以及注意事项 最近在一个项目中想做一个数据库查询的服务,目的是将数据库查询这块从程序中脱离出来,形成一个公共的服务平台,大家都可以调用,经过考虑决定选用Dubbo ...
- 为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! BigDecimal,相信对于很多人来说都不陌生,很多人都 ...
- 【PC工具】200412更新百度网盘下载工具——最终最简单百度网盘下载方法及注意事项...
今天有朋友在群里问会员账号,上次好像说过,这种公用的会员账号基本下载量都超了,同样也限速,所以这种账号一般都用来找资源. 百度网盘这个题材也来回来去发过好几个工具了,太麻烦不说,老这么道高一尺魔高一丈 ...
- 【PC工具】200324更新百度网盘下载工具——最新百度网盘下载工具使用方法及注意事项...
今天(200324)更新一个大牛的个人项目pdown,大家可以收藏一下备用(为啥是备用呢,细心的小伙伴应该发现我把标题中的高速两个字去掉了). 先发项目地址:没错还是那个神奇的网站(大神奇人聚集的地方 ...
- 【PC工具】更新百度网盘高速下载工具——亿寻使用方法及注意事项
之前分享的工具和方法大部分都不好用了,我也就不保留了,有需要的朋友可以翻看之前的历史文章. 今天分享一个目前比较主流的下载工具"亿寻",可能很多朋友都用过了,这里我简单说一下使用方 ...
- php获取表单$_files,PHP中$_FILES的使用方法及注意事项说明
$_FILES:经由 HTTP POST 文件上传而提交至脚本的变量,类似于旧数组$HTTP_POST_FILES 数组(依然有效,但反对使用)详细信息可参阅 POST方法上传 $_FILES数组内容 ...
- 佳能g3800故障灯说明书_汽车仪表灯的使用方法以及注意事项
能够准确地识别仪表盘上的数据是每个驾驶员的必要能力,但是如今,汽车技术日新月异,大量先进技术已应用于我们的爱车上.汽车仪表盘上的指示灯和中控台上的指示灯按钮变得越来越繁杂,准确识别这些抽象按钮已不再是 ...
- BigDecimal类setScale方法问题:算数异常,精确度丢失-ArithmeticException: Rounding necessary
BigDecimal类setScale方法问题:算数异常,精确度丢失-ArithmeticException: Rounding necessary 在运行如下代码时, package BigDeci ...
- 电脑安全注意事项_松下洗衣机维修方法及注意事项
阅读本文前,请您先点击上面的"蓝色字体",再点击"关注",这样您就可以继续免费收到文章了.每天都有分享,完全是免费订阅,请放心关注. 注:本文转载自网络,不代表 ...
- go面向对象编程:结构体struct详解、结构体实例的创建方式、结构体之间的转换(type取别名的使用)、方法的注意事项及与函数的区别
入门示例 package main import "fmt" //定义老师结构体,将老师中的各个属性 统一放入结构体中管理: type Teacher struct{//变量名字大 ...
最新文章
- html代码转换成为纯文本
- python外星人入侵游戏代码_Python游戏:外星人入侵游戏编程完整版!内附代码
- CentOS7安装配置redis5.0.5
- 安卓手机玩游戏卡顿怎么解决_手机卡顿怎么办?教你3个实用解决方法,两分钟解决卡顿难题!...
- css中改变边距会影响原大小,CSS:更改父容器中子项的边距会改变子项的宽度吗?...
- linux 第三章红帽子,红帽子 Linux_命令全解
- java对mysql的简单操作——增加数据
- 第四季 word vba
- Nginx核心原理揭秘:Nginx为什么高效?
- 安卓版 网易云音乐 6.4.3
- PS中标尺工具在哪里
- React 父组件获取子组件的方法/数据(useRef
- 邮储社招Java笔试题_2019年及历年中国邮政储蓄银行社招笔试题和参考答案6套
- Debugging RJS
- 虚拟主机服务器放在哪里,云虚拟主机的目录在哪里
- 【干货】java课程实战培训
- jquery-weui扩展功能Picker实现营业时间选择
- iOS原生二维码扫描(一)
- 高质量C++/C 编程指南
- HDFS Truncate文件截断
热门文章
- Python开发过程中错误解决记录【持续更新记录,欢迎交流】
- 基于face_recognition构建的人脸识别系统以及相关应用
- Python绘制散点对比图
- 2021-08-04 Mysql联表查询
- 如何通过ip访问服务器文件共享,通过ip访问云服务器文件共享
- 计算机组成原理2套题,计算机组成原理试卷2套含答案(大学期末复习资料).doc...
- python开发怎么成长_Python开发者四大进阶攻略,菜鸟的成神之路
- DevOps技术学习路线图 初阶+中阶+高阶
- FISCO BCOS 同态加密 实例
- linux .o,.a,.so文件区别是什么