zoukankan      html  css  js  c++  java
  • js中位运算的运用

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

    按位与(&)

    &&运算符我们都知道,只有两个都为真,结果才为真。&道理是一样的,只有两个数的值为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。

    总结

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

  • 相关阅读:
    使用Idhttp.get('') 造成假死(堵塞),请问线程idhttp怎么才能做到不出错?
    mysql 修改字段类型
    Delphi完成的断点续传例子 转
    断点续传的例子
    甲状腺癌怎样早发现 可B超检查
    DELPHI高性能大容量SOCKET并发(九):稳定性问题解决
    百度地图信息提示框的修改 转
    delphi 调用百度地图WEBSERVICE转换GPS坐标 转
    delphi 调用百度地图api
    Gedit
  • 原文地址:https://www.cnblogs.com/xljzlw/p/4231354.html
Copyright © 2011-2022 走看看