为什么8.1/3=2.6999999

看到这个问题好久了,看别的八股文也没有解释得很详细,这里我用最详细的方法解释一下


因为十进制的小数不能用二进制精确表示导致存放在float或double里的二进制小数很大概率只是一个近似值。所以使用近似值去运算得到的就是一个近似的结果

十进制转成二进制时,整数和小数是分开保存的


具体原因:整数转成二进制采用的是除2取余法,而小数转成二进制采用的是×2取余法可能会导致循环而导致余数是无尽的所以转换成二进制后是无限的,所以float或double会截断后面的一部分而保存一个精度丢失的二进制数。

有些小数使用×2取余法的余数不是无限的(比如上面的0.372),使用float或double能精确表示,但是其实大部分小数都无法精确表示。

可以使用bigDecimal来解决这个问题


BigDeciaml原理:bigDecimal是通过无标度值和标度来保存一个小数的,简单来说,无标度值就是去掉小数点后的整数,标度就是小数点应该右移的位数。

比如123.321,无标度值就是123321,标度就是3

0.1,无标度值就是1,标度就是1


但是使用时不能直接用构造器new BigDecimal(Double val)赋值,因为传一个double类型的数据就相当于将一个十进制转成二进制导致精度丢失后才传给它。所以我们要使用BigDecimal.valueOf(Double d)来创建,从源码可以看出,它是先将double类型的参数转为String类型,调用参数是String类型的构造器

然后拆分String字符串成char类型的字符,就可以得到精度未丢失的小数,BigDecimal就知道它要保存的小数是什么了,然后就根据bigDecimal的原理来保存这个小数

参考:https://blog.csdn.net/wang_luwei/article/details/122081436

https://blog.csdn.net/cnds123/article/details/130237430


有错误欢迎指正


0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
鱼友8300
下载 APP