js中位运算的运用实例分析


Posted in Javascript onDecember 11, 2018

我们可能很少在编程中用位运算,如果没深入学习,可能也很难理解。平时的数值运算,其实是要先转换成二进制再进行运算的,而位运算就是直接进行二进制运算,所以位运算的执行效率肯定是更高的。下面通过一些实例来加深对位运算的理解。

按位与(&)

&&运算符我们都知道,只有两个都为真,结果才为真。&道理是一样的,只有两个数的值为1时,才返回1。例如1和3的按位与操作:

    0001
&  0011
  ---------
    0001

只有对应的数为1时,结果才为1,其他都为0。
判断一个数是奇数还是偶数,我们会用求余数来判断:

function assert(n) {
  if (n % 2 === 1) {
 console.log("n是奇数");
 } else {
 console.log("n是偶数");
 }
}

assert(3); // "n是奇数"

我们也可以用一个数和1进行按位&操作来判断,而且速度更快:

function assert(n) {
if (n & 1) {
 console.log("n是奇数");
} else {
 console.log("n是偶数");
}
}

assert(3); // "n是奇数"

下面是位运算过程:

1 = 0001
3 = 0011
--------
   & = 0001

奇数的二进制码的最后一位数肯定是1,而1只有最后一位为1,按位&操作之后,结果肯定只有最后一位数为1。而偶数的二进制表示的最后一位数是0,和1进行按位&操作,结果所有位数都为0。

按位或(|)

|与||操作符的道理也是一样的,只要两个数中有一个数为1,结果就为1,其他则为0。

  0001
| 0011
 ---------
  0011

对浮点数向下求整,我们会用下面的方法:

var num = Math.floor(1.1); // 1

我们也可以用位运算来求整:

var num = 1.1 | 0; // 1

其实浮点数是不支持位运算的,所以会先把1.1转成整数1再进行位运算,就好像是对浮点数向下求整。所以1|0的结果就是1。

按位非(~)

按位非就是求二进制的反码:

var num = 1; // 二进制 00000000000000000000000000000001
var num1 = ~num; // 二进制 11111111111111111111111111111110

我们知道,js中的数字默认是有符号的。有符号的32位二进制的最高位也就是第一位数字代表着正负,1代表负数,0代表整数。那到底11111111111111111111111111111110等于多少呢?最高位为1代表负数,负数的二进制转化为十进制:符号位不变,其他位取反加1。取反之后为10000000000000000000000000000001,加1之后为10000000000000000000000000000010,十进制为-2。

按位异或(^)

按位异或是两个数中只有一个1时返回1,其他情况返回0。

   0001
^ 0011
 ---------
  0010

数字与数字本身按位异或操作得到的是0,因为每两个对应的数字都相同,所以最后返回的都是0。

我们经常会需要调换两个数字的值:

var num1 = 1, num2 = 2, temp;
temp = num1;
num1 = num2; // 2
num2 = temp; // 1

如果装逼一点的话,可以这样:

var num1 = 1, num2 = 2;
num1 = [num2, num2 = num1][0];
console.log(num1); // 2
console.log(num2); // 1

如果想再装的稳一点的话,可以这样:

var num1 = 1, num2 = 2;
num1 ^= num2; // num1 = num1 ^ num2 = 1 ^ 2 = 3
num2 ^= num1; // num2 = num2 ^ (num1 ^ num2) = 2 ^ (1 ^ 2) = 1
num1 ^= num2; // num1 = num1 ^ num2 = 3 ^ 1 = 2
console.log(num1); // 2
console.log(num2); // 1

有符号左移(<<)

有符号左移会将32位二进制数的所有位向左移动指定位数。如:

var num = 2; // 二进制10
num = num << 5; // 二进制1000000,十进制64

如果要求2的n次方,可以这样:

function power(n) {
 return 1 << n;
}

power(5); // 32

1的二进制是01,左移5位就是0100000,十进制就是2的5次方32。

有符号右移(>>)

有符号右移会将32位二进制数的所有位向右移动指定位数。如:

var num = 64; // 二进制1000000
num = num >> 5; // 二进制10,十进制2

求一个数的二分之一:

var num = 64 >> 1; // 32

有符号左移与右移不会影响符号位。

无符号右移(>>>)

正数的无符号右移与有符号右移结果是一样的。负数的无符号右移会把符号位也一起移动,而且无符号右移会把负数的二进制码当成正数的二进制码:

var num = -64; // 11111111111111111111111111000000
num = num >>> 5; // 134217726

所以,我们可以利用无符号右移来判断一个数的正负:

function isPos(n) {
return (n === (n >>> 0)) ? true : false; 
}

isPos(-1); // false
isPos(1); // true

-1>>>0虽然没有向右移动位数,但-1的二进制码已经变成了正数的二进制码:

11111111111111111111111111111111

所以-1>>>0的值为4294967295。

总结

以上的例子在平常可能会比较容易用到或看到,也是属于比较容易理解的。一些比较复杂的、难理解的,我觉得应该尽量少用,因为会给阅读者带来困难,也会给自己带来麻烦。

Javascript 相关文章推荐
jQuery学习笔记之jQuery选择器的使用
Dec 22 Javascript
jquery 利用show和hidden实现级联菜单示例代码
Aug 09 Javascript
js获取多个tagname的节点数组
Sep 22 Javascript
为开发者准备的10款最好的jQuery日历插件
Feb 04 Javascript
js二维数组定义和初始化的三种方法总结
Mar 03 Javascript
JavaScript遍历table表格中的某行某列并打印其值
Jul 08 Javascript
Angular @HostBinding()和@HostListener()用法
Mar 05 Javascript
jquery获取元素到屏幕四周可视距离的方法
Sep 05 jQuery
详解Node.js中path模块的resolve()和join()方法的区别
Oct 29 Javascript
JS module的导出和导入的实现代码
Feb 25 Javascript
JS apply用法总结和使用场景实例分析
Mar 14 Javascript
vue实现树状表格效果
Dec 29 Vue.js
js中的数组对象排序分析
Dec 11 #Javascript
详解Vue源码之数据的代理访问
Dec 11 #Javascript
浅谈Vue 性能优化之深挖数组
Dec 11 #Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
Dec 11 #Javascript
Vue入门之数量加减运算操作示例
Dec 11 #Javascript
简单的React SSR服务器渲染实现
Dec 11 #Javascript
Vuex 单状态库与多模块状态库详解
Dec 11 #Javascript
You might like
PHP中设置时区,记录日志文件的实现代码
2013/01/07 PHP
php修改NetBeans默认字体的大小
2013/07/02 PHP
php redis实现文章发布系统(用户投票系统)
2017/03/04 PHP
利用 fsockopen() 函数开放端口扫描器的实例
2017/08/19 PHP
php判断电子邮件是否正确方法
2018/12/04 PHP
CL vs ForZe BO5 第二场 2.13
2021/03/10 DOTA
基于JQuery的一个简单的鼠标跟随提示效果
2010/09/23 Javascript
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
2011/03/28 Javascript
javascript淡入淡出效果的实现思路
2012/03/31 Javascript
jQuery 1.7.2中getAll方法的疑惑分析
2012/05/23 Javascript
jquery表格内容筛选实现思路及代码
2013/04/16 Javascript
如何解决Jquery库及其他库之间的$命名冲突
2013/09/15 Javascript
js判断60秒以及倒计时示例代码
2014/01/24 Javascript
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
2015/08/21 NodeJs
jQuery插件Timelinr 实现时间轴特效
2015/10/04 Javascript
Javascript闭包与函数柯里化浅析
2016/06/22 Javascript
关于JS中二维数组的声明方法
2016/09/24 Javascript
原生JS实现循环Nodelist Dom列表的4种方式示例
2018/02/11 Javascript
如何用Node写页面爬虫的工具集
2018/10/26 Javascript
JavaScript中EventBus实现对象之间通信
2020/10/18 Javascript
Python实现从url中提取域名的几种方法
2014/09/26 Python
python打开文件并获取文件相关属性的方法
2015/04/23 Python
python3实现读取chrome浏览器cookie
2016/06/19 Python
Python中支持向量机SVM的使用方法详解
2017/12/26 Python
python获取代码运行时间的实例代码
2018/06/11 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
selenium+python自动化测试之多窗口切换
2019/01/23 Python
PyTorch中常用的激活函数的方法示例
2019/08/20 Python
PyCharm搭建Spark开发环境的实现步骤
2019/09/05 Python
Python While循环语句实例演示及原理解析
2020/01/03 Python
体育教育专业毕业生自荐信
2013/11/15 职场文书
法学专业毕业生求职信
2014/06/12 职场文书
趣味运动会标语口号
2015/12/26 职场文书
python 详解turtle画爱心代码
2022/02/15 Python
Java 获取Word中所有的插入和删除修订的方法
2022/04/06 Java/Android
使用pd.merge表连接出现多余行的问题解决
2022/06/16 Python