初学JavaScript,在进行小数(浮点数)运算时,常常会碰到这样的状况:0.1 + 0.2=0.30000000000000004
,记得当时,教程告诉咱们说,0.1 + 0.2
在JavaScript运算中,它的值是不固定的,能够在后面学习和试验中,渐渐发现,这个值彷佛每次都是0.30000000000000004
,因而渐渐怀疑当时学习过程当中关于它的和值是不固定的说法。前端
其实有必定编程基础的同窗们应该都知道,计算机是采用二进制来表示十进制的,规则是:整数除以2,商继续除以2,获得0为止,将余数逆序排列;小数乘以2,取整,小数部分继续乘以2,取整,获得小数部分0为止,将整数顺序排列
。例如:面试
其实无论是十进制转二进制仍是八进制、十六进制,原理都是同样的,即,基数连连除(整数)或者连乘(小数)编程
再回到咱们最初的问题, JS 采用 IEEE 754 双精度版本(64位),而且只要采用 IEEE 754 的语言都有前面的问题。post
IEEE 754 标准是IEEE浮点数算术标准(IEEE Standard for Floating-Point Arithmetic)的标准编号 ,等同于国际标准ISO/IEC/IEEE 60559 。IEEE 754 标准规定了计算机程序设计环境中的二进制和十进制的浮点数之间的交换、算术格式以及方法 。
根据前面介绍的知识,0.1 的二进制表示为:学习
0.1 = 2^-4 * 1.10011(0011)// (0011) 表示循环
0.2 的二进制表示为:spa
0.2 = 2^-3 * 1.10011(0011)// (0011) 表示循环
前面说了,JS 采用 IEEE 754 双精度版本(64位),六十四位中符号位占一位,整数位占十一位,其他五十二位都为小数位。由于 0.1 和 0.2 都是无限循环的二进制,因此在小数位末尾处须要判断是否进位(规则和十进制里的四舍五入同样)。
因此 0.1的二进制表示(0.1 = 2^-4 * 1.10011(0011)
) 进位后就变成了 2^-4 * 1.10011(0011 * 12次)010
,同理可得0.2的二进制表示 。把这两个二进制加起来获得 2^-2 * 1.0011(0011 * 11次)0100
, 这个值再换算成十进制就是 0.30000000000000004
。设计
因此说,0.1 + 0.2=0.30000000000000004
,在JavaScript中,它的结果并不是不固定的。3d
那么,若是须要比较0.1 + 0.2
和0.3
的关系,咱们又该如何进行呢?
其实对于在大学学过数学分析、数值逼近或者高中课程代数方面证实知识的同窗来讲,天然能够想到让0.1 + 0.2
的和减去0.3
小于一个任意小的数
,好比说咱们能够经过他们差值是否小于0.0000000001
来判断他们是否相等。JavaScript也提供了一些原生的方法,好比toFixed() 方法
可把 Number 四舍五入为指定小数位数的数字,语法:NumberObject.toFixed(num)
code
参数描述:num,必需。规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,有些实现能够支持更大的数值范围。若是省略了该参数,将用 0 代替。
参考内容:JavaScript toFixed() 方法
几道高级前端面试题解析blog