浮点计算精度丢失

为什么会浮点小数会出现精度丢失?

大家都应该都知道电脑的底层就是二进制吧,所有的操作最终都是在二进制中进行的,内存中只有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保留有效数字四舍五入。

参数为(小数位数,舍入方式)

示例图片:
浮点计算精度丢失