js精度缺失的问题

引言

这里呢,笔者先说说为啥要聊聊这个看起来似乎不太重要的问题吧,其实这还是得从笔者今天在一个技术群里遇到得一个疑问说起。笔者在偶然的刷群消息的时候,一个问题瞬间引起了笔者的注意:0.1 + 0.2 === 3吗?这个时候可能就会有人说,这还用问吗,肯定是对的啊。好吧,emmmmm…..,其实答案是否定的,下面就让笔者来聊聊这里面的坑吧。

0.1 + 0.2 为啥不等于 0.3 呢?

其实这里就涉及到js内部储存的一个问题了。在计算机领域当中呢,数字无论是定点数还是浮点数,都是以二进制的形式储存的。而在我们的js当中,数字是采用IEEE754的双精度标准进行储存,当然呢,这里我们也不用纠结这个内部到底是怎么储存的,我们可以单纯的理解为只是储存一个数字用到的二进制位数比较多而已,这样能更精确的表示数字。

举个栗子

对于整数来说,十进制的35会被存储为:00100011 其代表2^5 + 2^1 + 2^0

对于小数来说,十进制的0.375会被存储为: 0.011 其代表 1/2^2 + 1/2^3 = 1/4 + 1/8 = 0.375

这里就会有人问了,这个二进制小数是怎么转换的呢

十进制小数二进制表示法

这个方法其实很好理解:

文字描述该过程如下:将该数字乘以 2,取出整数部分作为二进制表示的第 1 位;然后再将小数部分乘以 2,将得到的整数部分作为二进制表示的第 2 位;以此类推,知道小数部分为 0。

特殊情况: 小数部分出现循环,无法停止,则用有限的二进制位无法准确表示一个小数,这也是在编程语言中表示小数会出现误差的原因

说一大段不如一个例子来的明确

/*就比如一个十进制小数0.6转为二进制*/
0.6 * 2 = 1.2 ------------ 1
0.2 * 2 = 0.4 ------------ 0
0.4 * 2 = 0.8 ------------ 0
0.8 * 2 = 1.6 ------------ 1
0.6 * 2 = 1.2 ------------ 1

很清晰的发现死循环了,那怎么办呢,这就该用到我们上面说的特殊情况了。看到这,大家也应该明白为什么js中会出现精度缺失的情况了。

二进制小数怎么转十进制呢

其实方法和普通的二进制转十进制差不多,话不多说,看栗子。

还是拿0.6来说事,它的二进制表示为

1001 1001 1001 1001 ...

转换一下就是

0.6 = 1 * 2^-1 + 0 * 2^-2 + 0 * 2^-3 + 1 * 2^-4 + ...

看完笔者的这篇文章,相信大家应该会有种恍然大悟的感觉,好吧,不瞒大家说,笔者当时也是这个表情。


   转载规则


《js精度缺失的问题》 Super man 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
bind bind
序言 这段时间笔者在忙着项目开展的过程中,多次涉及到了this指向的问题。当然,对于这个问题的解决办法我们可能用的最多的还是call、apply,他们的用法也基本差不多,区别可能也就是传参方式的不同了,不过,大家似乎忘了还有一个哥们bind
下一篇 
从输入url到页面渲染完整解析 从输入url到页面渲染完整解析
本文对一次完整的请求和渲染过程做了一个详细的总结,小伙伴如果觉得本文对你稍微有所帮助的话,可以给笔者点个赞,有疑问的地方欢迎私聊。 概述 DNS解析域名获取IP地址 发起http请求(TCP三次握手) 服务器处理请求,并返回请求资源
  目录