Algorithms_数据结构与算法_位运算符的巧技一二事

≡放荡痞女 提交于 2019-12-19 15:13:18

在这里插入图片描述

单目运算符、双目运算符、三目运算符

单目 双目 三目 -----> 参与运算的数字个数

在这里插入图片描述


运算优先级

百度百科: JAVA运算符优先级

在这里插入图片描述

看个例子

public static void main(String[] args) {
        int a = 10, b = 6;
        System.out.println("改变之前的数:a=" + a + ",b=" + b);
        a -= b++;
        System.out.println("改变之后的数:a=" + a + ",b=" + b);

    }

在这里插入图片描述

因为b++运算中先执行++,再返回后置++运算表达式(b++)的返回值(6)给-=运算符。 在这个程序中a-=b++等于a=a-b++=10-6,所以a=4。


i++ 和 ++i

1、首先,单独拿出来说++i和i++,意思都是一样的,就是i=i+1。

2、如果当做运算符来说,就是a=i++或者a=++i这样的形式。情况就不一样了。

先说a=i++,这个运算的意思是先把i的值赋予a,然后在执行i=i+1;

而a=++i,这个的意思是先执行i=i+1,然后在把i的值赋予a;

举个例子来说,如果一开始i=4。

那么执行a=i++这条语句之后,a=4,i=5;

那么执行a=++i这条语句之后,i=5,a=5;

同理,i–和--i的用法也是一样的。


位运算符

位操作只能用于整形数据,对float和double类型进行位操作会被编译器报错。

在这里插入图片描述


按位与运算【&】

双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相与
结果:只有对应的两个二进位均为1时,结果位才为1 ,否则为0。

   7 5  转换为二进制
        7 -- 00000111
        5 -- 00000101
    
    7&5
        00000111
        00000101
        --------------
        00000101  -----> 7&5 = 5 

按位或运算【|】

双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相或
结果:只要对应的二个二进位有一个为1时,结果位就为1。

  7 5  转换为二进制
        7 -- 00000111
        5 -- 00000101
    
    7|5
        00000111
        00000101
        --------------
        00000111  -----> 7|5 = 7
 


按位异或运算【^】

双目运算符,参与运算的数以补码方式出现。
作用:参与运算的两数各对应的二进位相异或
结果:当两对应的二进位相异时,结果为1。

 7 5  转换为二进制
        7 -- 00000111
        5 -- 00000101
    
    7^5
        00000111
        00000101
        --------------
        00000010  -----> 7^5 = 2


按位取反运算【~】

单目运算符。
作用:对参与运算的数的各二进位按位求反 ,通俗点说 1 变 0 , 0 变 1

    1001的求反运算为: ~(1001) 结果为: 011

左移运算

左移运算符“<<”是双目运算符
作用:把“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。
结果:左移n位就是乘以2的n次方

举个例子

例一:
a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)

a=00000011  ---> 十进制  3 


a << 4  ----->  3 << 4  ---->  3的二进制左移400000011
   |
   |   -->二进位向左移动4|
00110000   -----> 转换为 十进制 48 , 就是 3 * 2^4 = 3 * 16 = 48  


故: 左移n位就是乘以2的n次方



例二

在这里插入图片描述


右移运算

右移运算符“>>”是双目运算符
作用:把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。。
结果:右移n位就是除以2的n次方

例如:设 a=15,a>>2 表示把00001111右移为00000011(十进制3)

a=00001111 ---> 十进制  15


a >> 2  -----> 15 >> 2  ---->  15的二进制右移200001111 
   |
   |   -->二进制右移2, 把最后的211挤掉了,剩下的补0
   |
00000011 -----> 转换为 十进制 3 , 就是 15 / 2^2 = 15 / 4= 3  


故: 右移n位就是除以2的n次方


在这里插入图片描述

二进制间的移位比十进制间的计算效率高很多. 


x>>1;//相当于x/=2
x<<1;//相当于x*=2
x>>2;//相当于x/=4
x<<2;//相当于x*=4
x>>3;//相当于x/=8
x<<3;//相当于x*=8

应用

int型变量是奇数还是偶数?

 public static void main(String[] args) {

        //判断int型变量是奇数还是偶数

        /**
         *  分析
         *  十进制      二进制
         *    3 -----> 011
         *    4 -----> 100
         *    5 -----> 101
         *    6 -----> 110
         *
         *   奇数的最后一位 1
         *   偶数的最后一位 0
         *
         *   &      两个二进位均为1时,结果位才为1 ,否则为0
         *   |      两个二进位有一个为1时,结果位就为1
         *
         *   所以 & 合适
         *
         *   1的二进制 也是  1
         *
         *   3 & 1 ----> 011 & 001  ---> 001  ----> 对应十进制  1
         *   4 & 1 ----> 100 & 001  ---> 000  ----> 对应十进制  0
         *       ||
         *       ||
         *       ||
         *       ||
         *
         *   3&1 = 1 ---> 奇数
         *   4&1 = 0 ---> 偶数
         *
         *   所以
         *      a&1 = 1 奇数
         *      a&1 = 0 偶数
         *
         */

        for (int i = 0; i < 10 ; i++) {
            if ((i&1) == 1){
                System.out.println(i + " 奇数");
            }else{
                System.out.println(i + " 偶数");
            }
        }


    }

在这里插入图片描述


除数为2的n次方时,使用位操作(&运算)代替求余操作

当b为2的n次方时 , a % b = a & (b-1) (b=2^n)

 /**
         * 位运算比十进制的运算要高效,
         *
         * 在某些情况下,当b为2的n次方时,有如下替换公式:
         *         a % b = a & (b-1)  (b=2^n)
         *
         *      即:a % 2^n = a & (2^n-1)
         *
         *
         *    a = 12  , b = 2^3 = 8
         *
         *    12 % 8  取余操作 = 4
         *
         *    12 ------ 1100
         *    8  ------ 1000
         *    7  ------ 0111
         *
         *    12 & 7 ---- 1100
         *                0111
         *                --------
         *                0100 ---------->十进制 4
         */
        
        System.out.println(12 % 8);
        System.out.println(12&7);

在这里插入图片描述

看下JDK1.7 HashMap的实现 也是这样操作的。
在这里插入图片描述


int 类型的 整数 a 、b 交换位置

 /**
         *  int 类型的 整数  a 、b
         *  a 和 b 交换:
         *      常规思路 引入临时变量temp
         *
         *          int temp = a ;  a 赋值给临时变量 temp
         *          a = b ;     b赋值给a
         *          b = temp;   temp 赋值给b
         *
         *       异或^ 当两对应的二进位相异时,结果为1
         *
         *          a = 8 -------> 1000
         *          b = 9 -------> 1001
         *
         *          a ^= b;  --> a = a^b --> a = 1000 ^ 1001 --> a = 0001 --> a = 1
         * 		    b ^= a;  --> b = b^a --> b = 1001 ^ 0001 --> b = 1000 --> b = 8
         * 		    a ^= b;  --> a = a^b --> a = 0001 ^ 1000 --> b = 1001 --> a = 9
         *
         *
         */


        int a = 8, b = 9 ;

        System.out.println("before switch【 a:" + a + " b:" + b + "】" );
        if (a != b) {
            a^=b;
            b^=a;
            a^=b;
        }
        System.out.println("after switch 【 a:" + a + " b:" + b + "】" );


在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!