千家信息网

BigDecimal遇到的坑有哪些

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"BigDecimal遇到的坑有哪些",在日常操作中,相信很多人在BigDecimal遇到的坑有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Big
千家信息网最后更新 2026年11月02日BigDecimal遇到的坑有哪些

这篇文章主要介绍"BigDecimal遇到的坑有哪些",在日常操作中,相信很多人在BigDecimal遇到的坑有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"BigDecimal遇到的坑有哪些"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

避免用Double来进行运算

使用Double来计算,我们以为的算术运算和计算机计算的并不完全一直,这是因为计算机是以二进制存储数值的,我们输入的十进制数值都会转换成二进制进行计算,十进制转二进制再转换成十进制就不是原来那个十进制了,再也不是曾经那个少年了。举个例子:十进制的0.1转换成二进制是0.0 0011 0011 0011...(无数个0011),再转换成十进制就是0.1000000000000000055511151231,看到了吧,没有骗你的。

计算机无法精确地表达浮点数,这是不可避免的,这是为什么浮点数计算后精度损失的原因。

System.out.println(0.1+0.2); System.out.println(1.0-0.8); System.out.println(4.015*100); System.out.println(123.3/100);

通过简单的例子,我们发现精度损失并不是很大,但是这并不代表我们可以使用,特别是电商类系统中,每天少说几百万的单量,每笔订单哪怕少计算一分钱,算下来也是一笔不小的金额,所以说,这不是个小事情,然后很多人就说,金额计算啊,你用BigDecimal啊,对的,这个没毛病,但是用了BigDecimal就完事大吉了吗?当问出这句话的时候,就说明这其中必有蹊跷。

BigDecimal你遇见过哪些坑?

还是通过一个简单的例子,计算上边例子中的运算,来看一下结果:

System.out.println(new BigDecimal(0.1).add(new BigDecimal(0.2))); System.out.println(new BigDecimal(1.0).subtract(new BigDecimal(0.8))); System.out.println(new BigDecimal(4.015).multiply(new BigDecimal(100))); System.out.println(new BigDecimal(123.3).divide(new BigDecimal(100)));

我们发现使用了BigDecimal之后计算结果还是不精确,这里就要记住BigDecimal的第一个坑了:

BigDecimal来表示和计算浮点数的时候,要使用String的构造方法来初始化BigDecimal。

小的改进一下再来看看结果:

System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2"))); System.out.println(new BigDecimal("1.0").subtract(new BigDecimal("0.8"))); System.out.println(new BigDecimal("4.015").multiply(new BigDecimal("100"))); System.out.println(new BigDecimal("123.3").divide(new BigDecimal("100")));

那么接下来一个问题,使用了BigDecimal就万事大吉了吗?并不是的!

接下来我们来看一下BigDecimal的源码,这里面有一个地方需要注意,先看图:

注意看这两个属性,scale表示小数点右边几位,precision表示精度,就是我们常说的有效长度。

前边我们已经知道,BigDecimal必须传入字符串类型数值,那么如果我们现在是一个Double类型数值,该如何操作呢?通过一个简单的测试我们来看一下:

 private static void testScale() {      BigDecimal bigDecimal1 = new BigDecimal(Double.toString(100));      BigDecimal bigDecimal2 = new BigDecimal(String.valueOf(100d));      BigDecimal bigDecimal3 = BigDecimal.valueOf(100d);      BigDecimal bigDecimal4 = new BigDecimal("100");      BigDecimal bigDecimal5 = new BigDecimal(String.valueOf(100));       print(bigDecimal1);      print(bigDecimal2);      print(bigDecimal3);      print(bigDecimal4);      print(bigDecimal5);      }  private static void print(BigDecimal bigDecimal) {         System.out.println(String.format("scale %s precision %s result %s", bigDecimal.scale(), bigDecimal.precision(), bigDecimal.multiply(new BigDecimal("1.001")))); }

run一下我们发现,以上前三种方式是将double转换成BigDecimal之后,得到的BigDecimal的scale都是1,precision都是4,后两种方式的toString方法得到的scale都是0,precision都是3,与1.001进行乘运算后,我们发现,scale是两个数的scale相加的结果。

我们在处理浮点数的字符串的时候,应该显式的方式通过格式化表达式或者格式化工具来明确小数位数和舍入方式。

浮点数的舍入和格式化该如何选择?

我们首先来看看使用String.format的格式化舍入,会有什么结果,我们知道浮点数有double和float两种,下边我们就用这两种来举例子:

double num1 = 3.35; float num2 = 3.35f; System.out.println(String.format("%.1f", num1)); System.out.println(String.format("%.1f", num2));

得到的结果似乎与我们的预期有出入,其实这个问题也很好解释,double和float的精度是不同的,double的3.35相当于3.350000000000000088817841970012523233890533447265625,而float的3.35相当于3.349999904632568359375,String.format才有的又是四舍五入的方式舍入,所以精度问题和舍入方式就导致了运算结果与我们预期不同。

Formatter类中默认使用的是HALF_UP的舍入方式,如果我们需要使用其他的舍入方式来格式化,可以手动设置。

到这里我们就知道通过String.format的方式来格式化这条路坑有点多,所以,「浮点数的字符串格式化还得要使用BigDecimal来进行」。

来,上代码,测试一下究竟是不是那么回事:

BigDecimal num1 = new BigDecimal("3.35"); //小数点后1位,向下舍入 BigDecimal num2 = num1.setScale(1, BigDecimal.ROUND_DOWN); System.out.println(num2); //小数点后1位,四舍五入 BigDecimal num3 = num1.setScale(1, BigDecimal.ROUND_HALF_UP); System.out.println(num3); 输入结果: 3.3 3.4

这次得到的结果与我们预期一致。

BigDecimal不能使用equals方法比较?

我们都知道,包装类的比较要使用equals,而不能使用==,那么这一条在Bigdecimal中也适用吗?数据说话,简单的一个测试来说明:

System.out.println(new BigDecimal("1").equals(new BigDecimal("1.0"))) 结果:false

按照我们的理解1和1.0是相等的,也应该是相等的,但是Bigdecimal的equals在比较中不只是比较了value,还比较了scale,我们前边说了scale是小数点后的位数,明显两个值的小数点后位数不一样,所以结果为false。

实际的使用中,我们常常是只希望比较两个BigDecimal的value,这里就要注意,要使用compareTo方法:

System.out.println(new BigDecimal("1").compareTo(new BigDecimal("1.0"))) 结果:true

到此,关于"BigDecimal遇到的坑有哪些"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

结果 方式 格式 十进制 小数 点数 十进 例子 小数点 方法 精度 运算 两个 二进制 数值 问题 学习 接下来 位数 字符 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东万易互联网科技有限公司惠州分公司 中国互联网科技股 金融科技还是互联网 互联网科技与金融科技 互联网的科技创新 深圳齐家互联网科技 银优互联网科技有限公司 互联网科技类展会 甘肃拓世互联网科技有限公司 中国最先进互联网科技公司 安控科技rtu产品工业互联网 现代科技和互联网有关系吗 广州慧亚互联网科技怎么样 受益于互联网科技的高速发展 互联网科技人工智能实验室 工业互联网等科技实现智能化赋能 中科明德北京互联网科技 广州互联网高科技取餐柜 科技美学互联网 艺术 小牛互联网科技有限公司地址 上海挚品互联网科技有限公司 互联网科技工作委员会 注册互联网科技公司经营范围大全 乌鲁木齐新华智原互联网科技学校 济南有互联网科技公司吗 互联网第三次科技革命特征 米泉互联网科技专业怎么样 互联网科技品牌 互联网科技大佬云集 平安好医生打造互联网科技医疗
0