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

热门系列:


目录

  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)

扫描二维码关注公众号,回复: 14593712 查看本文章

为什么说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。

猜你喜欢

转载自blog.csdn.net/yy339452689/article/details/108256478