原创:蜀中ggdst说前端
小数运算问题
js中的小数运算一直有问题。
例如,0.1 0.2=0.30000000000004,0.4-0.3=0.100000000000003。
那为什么会发生这种事呢? 这种情况如何解决呢?
为什么?
这是关于js小数的记忆。 在js中查找其所有数字,包括小数和整数在内只有一种类型。 —编号。 实现了符合IEEE 754标准。 用64位固定长度表示。
这种存储结构的优点在于可以对整数和小数进行归一化处理,从而可以节省存储区域。
64位又分为三个部分。
符号位s )第一位为正负符号位(sign ),0为正数,1为负指数位e )中央11位存储器指数(exponent ),且乘数位m )的最后52位为尾数(mantissa )
实际数字可以用以下公式计算。
请注意,以上公式遵循科学计数法的规范,10进制为0m 10,2进制为0M2。 也就是说,整数部分只能是1,所以可以将其截断,只保留后面的小数部分(如果不接受这个理论,请参见下面的0.1示例)。
例如,将十进制的4.5变换为二进制数时为100.1,科学的计数法显示为1.001*2^2,舍去1后的M=001
e是无符号整数。 长度为11位,因此值的范围为0到0~2047。 但是,科学计数法中的指数可以为负数,所以再减去中间的数1023,[ 0,1022 ]为负,[ 1024,2047 ]为正。 4.5的指数E=1025时,尾数m为001。
最终公式如下
因此,4.5最终表示为(S=1、E=1025、M=001 );
用0.1个例子说明浮点误差的原因,从0.1转换为二进制表示为0.000110011001100 (1100个循环)、1.100110011001100x2^-4,因此E=-4 1023=1019; m舍弃了首位的1,100110011 . 如果转换为十进制数,则为0.1000000000000055115123126,因此会产生浮点误差。
小数是怎么转换成二进制数的呢?
小数二进制
例如数字3.2向二进制转移的过程;
第一步: 0.32*2=0.64,此时整数部分为0,如果第一位为0,则第0.0二步: 0.64*2=1.28,此时整数部分为1,如果第二位为1,则第0.01三步:取一后的1.28减去1 此时,整数部分为0,因此第三位为0。 于是,0.010第四步: 0.56*2=1.12。 此时,整数部分为1,因此第四位为1。 于是,变为0.0101。 第五步:和第三步的想法一样,一直持续到最后一个小数部分消失的时候。 为什么要乘以2,是因为使用二进制数据表示数时,只有2位、0和1。 怎么解决这个问题呢
第一个
把小数转换成整数再运算。 以加法为例:
0.1 0.2
把所有数字都乘以他们可以转换为整数的倍数,计算后除以相乘的倍数。 例如,(0.1*10 0.2*10 )/10
第二类
另一个方案是建立自己的计算过程,例如0.1 0.2。 首先,通过正则、AST和其他分析方法,使符号与数字一致,按照四则运算法的法则计算文字。 0.1和0.2取小数位数后加减第一位。 是否进入1,注意到不需要加减整数位的第一位,依次递归进行。 这个方法的想法和我们的立式计算一样,是对立式计算的想法进行编码的。 现在,我们找到了小数的计算和原因。 扩展后,作为计算机基础的cpu如何进行加减乘除运算呢? 想进入小组讨论最后进入前端小组的人可以加微信。 备注:玄说的是前端。
结束
获取更多信息关注公众号