最近在读javascript高级程序设计关于浮点数的那一节中看到这个问题,然而,0.15 + 0.15却等于0.3,有些好奇,于是百度特此记录下来
为什么?
因为有关于数值的计算,是要在计算机内完成的,因此我们输入的数值,最终都会转化为二进制的01串进入cpu的计算模块进行计算,计算结果也是以二进制输出然后转化为10进制显示的,这里就涉及到了进制转化问题:
10 to 2 进制转化:
10进制 | 2进制 |
---|---|
0.1 | 0.000110011.... |
0.375 | 0.011 |
转化规则
10进制数乘以2后
0.1 * 2 = 0.2 取整数0
0.2 * 2 = 0.4 取整数0
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.0001100011…..
0.375 * 2 = 0.75 取整数0
0.75 * 2 = 1.5 取整数1,再继续取小数部分运算
0.5 * 2 = 1 取整数1 直到结果为整数,或者到要求的精度位置
像0.1,0.2这种化为2进制后一直循环的数,由于储存空间有限,最后计算机会舍弃后面的值,所以我们得到了一个近似值:0.30000000000000004,这当然不等于0.3
那么问题来了,为什么0.15+0.15 == 3 为true呢,0.15化为2进制不也是循环的序列吗?
我们先来看一个例子
console.log(0.1000000000000001)(中间14个0)
结果:0.1000000000000001
console.log(0.10000000000000001)(中间15个0)
结果:0.1
我们发现在js中,如果这个近似值足够近似,那么Js就会认为它就是那个值,比如上方的第二个例子。这就是0.15+0.15能等于3为什么能得到正确的答案
但在实际情况中,我们根本不知道哪些数字能够在近似后得到本身,所以我们要在源头上解决这个问题。
化浮点数计算为整数计算
例如:
对于0.1 + 0.02 我们可以转化成(10+2) / 1e2
对于0.1 * 0.02 我们可以转化成 1*2 / 1e3
网友评论