JS神奇的或0(|0)

简介: 可以看到明显的带或0运算与不带或0运算的结果无论是位数还是符号位都有不同。那这中间到底发生了什么?这里找一个数字为例:117063531626496要想验证这个问题,思路如下:1,对比变更前后的数字的二进制格式2,找到是否有数字表示的安全边界首先按照思路1,我们看一下这个数字和这个数字或0后的二进制格式分别是什么:

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位的1:
var 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进行位运算则可能得到一个错误的结果。

分类: Javascript

相关文章
|
机器学习/深度学习 存储 人工智能
|
消息中间件 安全 Kafka
Kafka保证消息不丢失不重复
Kafka保证消息不丢失不重复
299 6
|
关系型数据库 数据库 索引
AnalyticDB for PostgreSQL 黑科技解析 - 列存储 Meta Scan 性能加速
本文介绍阿里云 AnalyticDB for PostgreSQL(原HybridDB for PostgreSQL) 产品,即 MPP 数据仓库服务,其列存储 meta scan机制,及其对 分析场景的性能提升。
2944 0
|
存储 缓存 安全
网络文件系统 (NFS)
【10月更文挑战第11天】
463 1
|
11月前
|
机器学习/深度学习 监控 算法
机器学习在图像识别中的应用:解锁视觉世界的钥匙
机器学习在图像识别中的应用:解锁视觉世界的钥匙
1440 95
|
10月前
|
机器学习/深度学习 PyTorch 测试技术
LossVal:一种集成于损失函数的高效数据价值评估方法
LossVal是一种创新的机器学习方法,通过在损失函数中引入实例级权重,直接在训练过程中评估数据点的重要性,避免了传统方法中反复重训练模型的高计算成本。该方法适用于回归和分类任务,利用最优传输距离优化权重,确保模型更多地从高质量数据中学习。实验表明,LossVal在噪声样本检测和高价值数据点移除等任务上表现优异,具有更低的时间复杂度和更稳定的性能。论文及代码已开源,为数据价值评估提供了高效的新途径。
234 13
LossVal:一种集成于损失函数的高效数据价值评估方法
|
9月前
|
机器学习/深度学习 计算机视觉
YOLOv11改进策略【Neck】| 2023 显式视觉中心EVC 优化特征提取金字塔,对密集预测任务非常有效
YOLOv11改进策略【Neck】| 2023 显式视觉中心EVC 优化特征提取金字塔,对密集预测任务非常有效
267 8
|
XML 移动开发 前端开发
JS设置Ajax为同步或异步
JS设置Ajax为同步或异步
394 0
|
前端开发 程序员 调度
探索协程在 C++ 中的实现方式
探索协程在 C++ 中的实现方式
347 2
|
数据采集 分布式计算 关系型数据库
Sqoop与Flume的集成:实时数据采集
Sqoop与Flume的集成:实时数据采集