你不知道的JavaScript--数值表示

JavaScript中数字的相关

这部分介绍了JavaScript数值相关的一些比较底层的知识和概念,阅读之前,要对IEEE754的数值表示有个大概的理解。本文是个人积累的一点关于数值方面存在的问题,以及对问题原因的解释。

1.MAX_VALUE与Infinity

  为什么Number.MAX_VALUE + 1 !=Infinity ?
  首先我们要看看在IEEE种二者分别是怎么表示的。
  在IEEE中,11位指数位的全部置1,尾数52位全部置0,表示Infinity。具体IEEE754的格式如下图
这里写图片描述
  而11位指数位的前10位都置1,最后一位置0,并且所有尾数置1来表示最大值,即MAX_VALUE。如下图:

这里写图片描述
  这就是JavaScript 中的 Number.MAX_VALUE: 1.7976931348623157e+308。

  在IEEE754的 4.1节中对Infinity 有这样的描述:

However, an infinitely precise result with magnitude at least

(2Emax)(221p2) ( 2 E m a x ) ∗ ( 2 − 2 1 − p 2 )
shall round to INFINITY with no change in sign;

  这段话的意思是指,只有大于上面这个式子所代表的值时,才会得到Infinity。所以根据IEEE754对双精度浮点数的规定,上面的式子可以表示为:

(21023)(221532)=210242970=(2541)2970 ( 2 1023 ) ∗ ( 2 − 2 1 − 53 2 ) = 2 1024 − 2 970 = ( 2 54 − 1 ) ∗ 2 970

  所以,实际Number.MAX_VALUE距离Infinity的差距就是上面这个式子的值与Number.MAX_VALUE的差,这个差值大概为

(2970) ( 2 970 )

2. 最大的安全整数值?

1.为什么最大的安全整数是(2^53-1)?

  我们知道,JavaScript中最大的安全整数是(2^53-1) 。安全意味着不超过这个数的每个整数都有一个唯一的浮点数表示,即一对一的。
比如为什么2^53不安全,虽然它表示正确,但实际上,已经丢失了精度。

  可以看看下面console打印出来的结果

 alert(9007199254740992 == 9007199254740993);//会alert出true来Math.pow(253)+ 1 = Math.pow(253);//会alert出true来

2.为什么是2^53而不是2^52
  因为IEEE754规定尾数第一位隐含为1,是不写的。所以这样就多了一位,可以最多表示为53位。

3. 相等吗?

0.1 + 0.2 !=0.3  //true
//实际在控制台:
0.1 + 0.2 = 0.30000000000000004//另外的例子
0.1 + 1 - 1 != 0   //false

  上面的小数部分0.1和0.2都不能精确地表示为二进制浮点数。
  这是因为小数不能在52位的尾数中转换成有限的二进制表示,实际上多少位都无法完全表示,就像我们知道的0.3333….的无限循环,所以造成精度丢失。在这里,0.1这个十进制小数在计算机中被转换为为二进制进行运算的时候,转换出来的二进制数是无限循环的,而双精度的尾数位是根本存不下这么多数字,所以会产生舍入,这个舍入导致了精度的丢失。在0.1~0.9的这9个小数中,只有0.5能够精确表示。
  怎么保证这样的运算安全。实际上,有小数输入时候,不应该直接比较它们,而是允许它们有一定的误差上限,这个误差上限称为机器精度(epsilon)。对于JavaScript,双精度的标准机器精度值是2^ -53

   var epsEqu = function () { // IIFE, keeps EPSILON private
        var EPSILON = Math.pow(2, -53);
        return function epsEqu(x, y) {
            return Math.abs(x - y) < EPSILON;
        };
    }();

  在ES6中,目前也已经提供了这个数值:Number.EPSILON。

4. 存在的转换

  数字的表示 当整数的位数超过21的时候,会被转换成科学记数法 对于小数,当小数是以0.开始,并且紧后面是连续超过5个0.会被转换成科学记数法

>1234567890123456789012
   1.2345678901234568e+21
>123456789012345678901
   123456789012345680000

>0.0000003
   3e-7
>0.000003
   0.000003

引用

  1. IEEE 754文档
  2. How numbers are encoded in JavaScript
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值