Layman解释为什么JavaScript有奇怪的浮动数学 - IEEE 754标准

Sam*_*Sam 4 javascript ieee-754

当我对浮点数进行数学运算时,我永远无法理解JavaScript究竟发生了什么.我一直都很害怕使用小数,直到我尽可能地避开它们.但是,如果我知道在IEEE 754标准中幕后发生了什么,那么我将能够预测会发生什么; 有了可预测性,我会更自信,更不可怕.

可能有人给我一个简单的解释(如解释整数的二进制表示法简单就如何IEEE 754标准的作品,以及它如何使这种副作用:0.1 + 0.2 != 0.3

非常感谢!:)

tho*_*ter 10

像0.1这样的小数部分不能在基数2中干净地表达

假设我们想在base-2中表示小数0.1.我们知道它等于1/10.在base-2中1除以10的结果是0.000110011001100...重复的小数序列​​.

因此,在十进制形式中,实际上很容易干净地表示像0.1这样的数字,在base-2中你无法准确地表达基于10的有理数.您只能通过使用您能够存储的多个位来近似它.

让我们说简化,我们只有足够的存储空间来重现该数字的第一个,例如8个有效二进制数字.存储的数字为11001100(指数为11).这转换回基数为2的0.000110011,十进制为0.099609375,而不是0.1.这是将0.1转换为理论浮点变量时会发生的错误量,该变量将基值存储为8位(不包括符号位).

浮点变量如何存储值

IEEE 754的标准规定了一种用二进制编码实数的方法,带有符号和二进制指数.指数应用于二进制域,这意味着在转换为二进制之前不会移位小数点,之后就会这样做.

IEEE浮点数有不同的大小,每个浮点数指定基数使用了多少二进制数字,指数使用了多少二进制数字.

当你看到时0.1 + 0.2 != 0.3,这是因为你实际上并没有在0.1或0.2上执行计算,而是在浮点二进制的这些数字的近似值上只有一定的精度.在将结果转换回十进制时,由于此错误,结果将不会精确为0.3.另外,结果甚至不等于0.3的二进制近似值.实际的错误量取决于浮点值的大小,因此使用了多少精度位.

四舍五入有时会有所帮助,但在这种情况下并非如此

在某些情况下,由于转换为二进制文件时精度损失导致的计算错误将足够小,可以在从二进制文件转换回来的过程中从舍入值中消失,因此您甚至不会注意到任何差异 - 它看起来就像它工作.

IEEE浮点具有关于如何进行舍入的特定规则.

然而,对于0.1 + 0.2对0.3,舍入不会抵消错误. 加上0.1和0.2的二进制近似值的结果将与0.3的二进制近似值不同.