【Java编程系列】二进制如何表示小数?0.3+0.6为什么不等于0.9?纳尼!!!

Java专栏 专栏收录该内容
64 篇文章 6 订阅

热门系列:


目录

  1.序言

  2.正题

  3.如何解决精度丢失


1.序言

如题所述,小数用二进制的方式怎么表示呢?小数相加为什么会出现精度丢失呢,在哪里丢失的呢?

如果做支付类,金融类业务和money打交道的开发,你会关注这些细节点吗?


2.正题

2.1 小数的二进制表示方式

小数的整数部分,按正常的二进制转换即可。小数部分,则需要按如下规则进行转换:

将该小数单独乘以2,取出整数部分作为二进制表示的第1位;然后再将小数部分乘以2,将得到的整数部分作为二进制表示的第2位;以此类推,直到小数部分为0为止!

举个特殊的例子,比如 0.6 的二进制表示如下:

0.6 * 2 = 1.2  →  取整数,为 1 
0.2 * 2 = 0.4  →  取整数,为 0 
0.4 * 2 = 0.8  →  取整数,为 0
0.8 * 2 = 1.6  →  取整数,为 1

0.6 * 2 = 1.2  →  取整数,为 1 
0.2 * 2 = 0.4  →  取整数,为 0 
0.4 * 2 = 0.8  →  取整数,为 0
0.8 * 2 = 1.6  →  取整数,为 1

…………  (循环往复,直至小数位为0)

为什么说0.6特殊,相信看到你这里你会发现,这种转二进制的方式,会导致0.6永远都不可能被转换完成,进入了一个无线循环的状态。所以,这也是在编程语言中表示小数会出现误差的原因!

例如,0.3 + 0.6 ,按理说应该是等于0.9,但实际却不是的。通过浏览器控制台输入下面这段代码,

你会发现并没有出现我们所期望的0.9 。作为一个java开发者,我们知道float,double的精度不一样,但是都会有精度丢失的情况。所以,这个精度在哪里丢失的呢?就是上面这种,由10进制数转换成2进制数时,计算机的转换方式导致的。


3.如何解决精度丢失

先看个例子:

java面试官:Double为什么会丢失精度?解决方法?答出给1万月薪

上面的代码输出为:

0.299999999999999988897769753748434595763683319091796875

0.3

由此可见,BigDecimal可以解决精度丢失的问题。原理是:BigDecimal在处理的时候把十进制小数扩大N倍让它在整数上进行计算,并保留相应的精度信息。所以,我们在开发时候,涉及到数字或是金额等方面的高精度化的情况时,就可以使用BigDecimal进行处理。

再说一下,我平时处理金额方面的使用情况。一般,我们的业务金额,基本就是需要精确到小数点后两位,也就是0.00,精确到分即可。所以,我每次都是将金额以 分 为单位,这样一来,就只会以整数的情况来做加减乘除了,不过如果出现了小数,还得使用BigDecimal。

 

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页

打赏

善良勤劳勇敢而又聪明的老杨

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值