经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
JS神奇的或0(|0)
来源:cnblogs  作者:原子切割员  时间:2024/6/25 8:51:57  对本文有异议

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

  1. 不带或0运算:
  2. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  3. 168546249998336
  4. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  5. 18707488702464
  6. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  7. 15579009253376
  8. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  9. 194841754140672
  10. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  11. 262611854950400
  12. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )
  13. 171394313420800
  14. 带或0运算:
  15. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
  16. -1037238272
  17. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
  18. 511180800
  19. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
  20. 1204224000
  21. (window.crypto.getRandomValues(new Uint32Array(1))[0] * 0x10000 )|0
  22. -2026438656

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

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

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

  1. 117063531626496的二进制格式:
  2. var num = 117063531626496; num.toString(2);
  3. 输出:'11010100111011111111010001110000000000000000000'
  4. 117063531626496 | 0
  5. 输出:-96993280
  6. -96993280的二进制格式:
  7. var num = -96993280; num.toString(2);
  8. '-101110010000000000000000000'

对比对比:

  1. 11010100111011111111010001110000000000000000000
  2. -101110010000000000000000000

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

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

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

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

  1. 9007199254740991|0
  2. -1
  3. 9007199254740990|0
  4. -2

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

  1. 2147483647|0
  2. 2147483647
  3. 如果对这个值再+1,重试呢
  4. 2147483648|0
  5. -2147483648

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

原文链接:https://www.cnblogs.com/bigjor/p/18264965

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号