来自小姐姐的灵魂拷问:位运算是什么?
前两天上班,突然小叶给我发消息:哥哥,你看这两段代码是什么意思啊?
乍一看,感觉这代码既熟悉又陌生。好像在哪里见过,但平时好像又很少用到。
我:没问题,等我整理一下~
哈哈,其实如果不是科班出身的同学,对二进制有点陌生也正常了。下面我就简短的介绍一下二进制
。
二进制
我们常用的 2、8、16 等数字是十进制表示,而位运算的基础是二进制。即人类采用十进制,机器采用的是二进制,要深入了解位运算,就需要了解十进制和二进制的转换方法和对应关系。
十进制转二进制
十进制整数转换为二进制整数采用除2取余,逆序排列
法。具体做法是:用 2 整除十进制整数,可以得到一个商和余数;再用 2 去除商,又会得到一个商和余数,如此进行,直到商为小于 1 时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
这里以十进制数 156 为例:
介绍完了二进制和十进制的相互转换,下面我们就来看下在js
中经常用到的几个位运算符吧。
JS 中常用的 7 个位运算符
基本的位运算共 7 种,分别为
-
按位与(AND) &
-
按位或(OR) |
-
按位异或(XOR) ^
-
按位非(NOT) ~
-
左移(Left shift)<<
-
有符号右移>>
-
无符号右移>>>
这里用一个表格来汇总下以上 7 种运算符的简介:
按位与(AND) &
&
运算符(位与)用于对两个二进制操作数逐位进行比较。如果对应的位都为 1,那么结果就是 1, 如果任意一个位是 0 则结果就是 0。
按位异或(XOR) ^
^
运算符(位异或)用于对两个二进制操作数逐位进行比较。只有两个对应位不同时才为 1。
这里稍微有些麻烦,做下解释:1 反码二进制表示: 11111111 11111111 11111111 11111110
。由于第一位(符号位)是 1,所以这个数是一个负数。JavaScript 内部采用补码
形式表示负数,即需要将这个数减去 1,再取一次反,然后加上负号,才能得到这个负数对应的 10 进制值。
1 的反码减 1 为:11111111 11111111 11111111 11111101
。
反码取反:00000000 00000000 00000000 00000010
。再加上符号位-
。最终得到 1 的按位非为-2
。
二进制数的负数是取该二进制数的补码,然后+1。二进制数,最高位为 0 表示正数,最高位为 1 表示负数。
~
按位非操作其实就是取补码的过程,也就是上述求该值负数的逆过程,所以可以简单的理解为该值取负值后减 1。
这里其实是有一个小技巧的:一个数与自身的取反值相加等于-1
。
左移(Left shift)<<
<<
运算符(左移)表示将指定的二进制向左移动指定的位数。
在MDN
上你可以看到:
同样,有一个核心词语:zero-fill right shift
。翻译过来就是零-填充
,这个就更明显了,右移后空位不管你符号位是什么,我都只填 0。
这里就可以得到一个结论:对于非负数,有符号右移和无符号右移总是返回相同的结果
。
到这里,JS 中常用的 7 个位运算符的介绍就差不多了。下面让我们来看下React
中对于按位运算符
的使用场景。(毕竟这是我第一次在实际的业务场景中看到有人用按位运算符的)
比较常规的,就是不断除以 2,判断最终结果是否为 1,也就是采用递归
的方法。
/** * @param {number} n * @return {boolean} */ var isPowerOfTwo = function(n) { if (n < 1){ return false; } if (n == 1) { return true; } if (n % 2 > 0) { return false; } return isPowerOfTwo(n / 2); };
我们考虑一下有没有更快的解决方式:观察 2^0、2^1、2^2……2^n,它们的二进制表示为 1、10、100、1000、10000……
判断一个数是否是 2 的 n 次幂,也就是判断二进制表示中是否只有一位是 1 且在最前面那位的位置。例如 n=00010000,那 n-1=00001111,即n&(n-1)==0
由此就可以判断啦!
/** * @param {number} n * @return {boolean} */ var isPowerOfTwo = function(n) { return n > 0 && (n & (n-1)) === 0 };
位 1 的个数
❤️ 爱心三连
1.如果觉得这篇文章还不错,来个分享、点赞、在看三连吧,让更多的人也看到~
2.关注公众号前端森林,定期为你推送新鲜干货好文。
3.特殊阶段,带好口罩,做好个人防护。
本文文字及图片出自 InfoQ
你也许感兴趣的:
- 【外评】电脑从哪里获取时间?
- 【外评】为什么 Stack Overflow 正在消失?
- Android 全力押注 Rust,Linux 却在原地踏步?谷歌:用 Rust 重写固件太简单了!
- 【外评】哪些开源项目被广泛使用,但仅由少数人维护?
- 【外评】好的重构与不好的重构
- C 语言老将从中作梗,Rust for Linux 项目内讧升级!核心维护者愤然离职:不受尊重、热情被消耗光
- 【外评】代码审查反模式
- 我受够了维护 AI 生成的代码
- 【外评】Linux 桌面市场份额升至 4.45
- 【外评】作为全栈开发人员如何跟上 AI/ML 的发展?
你对本文的反应是: