浮点计算精度丢失
为什么会浮点小数会出现精度丢失?
大家都应该都知道电脑的底层就是二进制吧,所有的操作最终都是在二进制中进行的,内存中只有0和1
接下来给大家演示一下十进制整数在二进制中是如何储存的。
例1:17的二进制为:
17/2 = 8余(1)
8/2 = 4余(0) 4/2 = 2余(0) 2/2 = 1余(0) 1/2 = 0余(1)
也就是17在二进制中表示为(反向取余) 10001
而小数呢?小数无法被除为0了那么小数在二进制中如何显示呢?
十进制小数在二进制中是如何储存的。
例2:0.7的二进制为:
0.7 * 2 = 1.4 取整数部分1 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.7的二进制为(正向取整)101100…
上面的进制转化计算出现了循环也就是说乘2永远无法等于整数而不是小数。
所以二进制表示的小数是精确的而不是确切的。
小数无法确切的储存在二进制中,而小数计算是通过二进制完成的,所以出现了精度丢失。
Java浮点计算精度丢失解决方案
采用BigDecimal类对浮点进行转化。
(优先字符串,整数,尽量不要浮点类型)
在通过add,subtract,multiply,divide进行加减乘除的计算。
注意:在进行除法的时候可能出现不能整除的情况会报错
除法divide可以传三个参数【除数,保留小数位数,舍入模式(ROUND_HALF_UP四舍五入……等)】
setScale方法可以对BigDecimal保留有效数字四舍五入。
参数为(小数位数,舍入方式)
示例图片: