• JS神奇的或0(|0)


    按照常识,位运算x|0,要么等于x,要么等于0
    那么在JS的世界你的认知就要被颠覆了
    下面请看

    不带或0运算:
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    168546249998336
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    18707488702464
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    15579009253376
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    194841754140672
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    262611854950400
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
    171394313420800
    
    带或0运算:
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
    -1037238272
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
    511180800
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
    1204224000
    (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
    -2026438656
    

    可以看到明显的带或0运算与不带或0运算的结果无论是位数还是符号位都有不同。
    那这中间到底发生了什么?

    这里找一个数字为例:117063531626496
    要想验证这个问题,思路如下:
    1,对比变更前后的数字的二进制格式
    2,找到是否有数字表示的安全边界

    首先按照思路1,我们看一下这个数字和这个数字或0后的二进制格式分别是什么:

    117063531626496的二进制格式:
    
    var num = 117063531626496; num.toString(2);
    输出:'11010100111011111111010001110000000000000000000'
    
    117063531626496 | 0
    输出:-96993280
    
    -96993280的二进制格式:
    var num = -96993280; num.toString(2);
    '-101110010000000000000000000'
    

    对比对比:

    11010100111011111111010001110000000000000000000
                       -101110010000000000000000000
    

    除了后面的0位数相同,没有找到明显的线索

    那么我们按照思路2,来看一下原因:
    通过官网对于js的number的定义,是64位的统一类型
    但是我们通过 Number.MAX_SAFE_INTEGER可以看到number的安全最大值是:9007199254740991

    通过转为2进制,可以发现这个数字是个54位的1var num = 9007199254740991; num.toString(2)
    '11111111111111111111111111111111111111111111111111111'
    

    那这个值可以正常地或0吗?实际上还是不行

    9007199254740991|0
    -1
    9007199254740990|0
    -2
    

    那这个边界到底是多少呢?对于其它语言Integer的默认最大值一般为2的32次方-1,也就是2147483647
    这次再来试一下:

    2147483647|0
    2147483647
    如果对这个值再+1,重试呢
    2147483648|0
    -2147483648
    

    可以发现这个边界就是32位整数的最大值。
    超过这个值的数字再与0进行位运算则可能得到一个错误的结果。

  • 相关阅读:
    《代码整洁之道》读书笔记(二)
    上海-华为合作伙伴之夜:创新领导力 | 竹云荣膺“华为全球杰出行业解决方案合作伙伴奖”
    Docker容器环境变量设置与查看
    NFS安装配置
    sCrypt 合约中的椭圆曲线算法:第二部分
    Python 基于docker部署的Mysql备份查询脚本
    报表如何动态切换数据源
    Lwip之TCP客户端示例记录
    Spring Security 安全框架NOTE
    【Android面试八股文】在onResume中是否可以测量宽高?
  • 原文地址:https://www.cnblogs.com/bigjor/p/18264965