位运算---------图解及代码演示(gan货技巧满满,适合初学者)

简介: 位运算---------图解及代码演示(gan货技巧满满,适合初学者)

前言


       有一天你要去面试,你信心满满,什么数据库索引优化,jvm内存管理你都倒背如流。和你一起面试的还有一个看上去非常年轻像毕业的学生,你对他不屑一顾。见了面试官,你已经准备好了应付他的难题,只见面试官微微一笑:“请问现在有两个int变量a,b,在不创建新变量的情况下,如何交换他们的值呢?”你有点懵逼,在纸上思前上去也毫无头绪,难道不创建新变量还能交换值?只见那位学生微微一笑,提笔写了几下便交给面试官,只见面试官满意的点点头,而你却尴尬地坐在原地(欲知后事请往下看)


1.什么是位运算?


       首先,我们要知道,我们地计算机存储数据的形式都是二进制。就是所有的东西他都是转化位二进制来保存,而二进制只有0和1两个数字,我们的位运算就是在二进制的基础上进行运算,它是一个二元运算符,就是对两个数据进行操作。它是编程语言中最难最复杂的运算,所以专门用一篇文章讲解。如果你还没了解其他的运算,推荐看看我的这篇文章,非常适合新手


搞定编程语言所有基础运算(图解,详细代码)


2.位运算有那些?


1.按位与&

按位与的符号与我们逻辑运算符的逻辑与是一样的,都是&。那&啥适合是按位与啥时候又是逻辑与呢?当我们&左右两边是整型变量时,它代表的是按位与。当左右两边是布尔值时,它是逻辑与。   1&1=1  1&0=0  0&0=0


按位与&的逻辑是:如果两个对应的二进制位都位1,则该位的结果值为1,否则为0  


通过下图能直观的表示。


image.png


PS:我们知道在逻辑与中两个true才是真的true,而在代码中,往往1代表true,0代表false。所以两个1代表真的1,这样方便我们记忆。


2.按位或 |


       按位或 | 符号与我们的的逻辑或符号相同,都是 | 。它的意思和我们的按位与相反。当左右两边只要有一个1则就为1,同理与上面的记法。或者你可以记成按位与&是都为1才为1,按位或|是都为0才为0。  1|1=1   1|0=1  0|0=0      


同样通过一个图进行理解:


image.png


3.异或^


       异或的符号是^,一般按键盘的shift加6,如果输出的是……这样则需要切换成英文键盘。异或的规则是两个位数相同则位0,否则位1。因为它的名字带一个异,而异的意思就是不同,说明如果是不同的话就说明是真的那就是1,都一样的话那就是相同的,则是假的,记为0.            1^1=0            1^0 =1               0^0=0


前言解答:


你拿过纸上看了看,只见上面简便地写着:


public static void main(String[] args) {
        int a=10;
        int b=12;
        a=a^b;
        b=a^b;
        a=a^b;
        System.out.println(a);//12
        System.out.println(b);//10
    }

你惊讶地看着这短短地代码,于是在纸上演算了起来


image.png


解析:我们可以发现,12和10异或得到一个数6,这个6和他们之间任何一个再次异或后可以得到另外一个。我们暂时将这个数6成为中转数,即6再和12异或又得回了10,再和10异或又得回12,这三个数互相异或都会得到另外一个。这个性质就产生了前言的替换功能,没有借助多余的变量,是不是很神奇


4.取反运算符~与左右移运算符<<  >>

  • ~


  • 取反


  • ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1


  • <<


  • 左移


  • 用来将一个数的各二进制位全部左移N位,右补0


  • >>


  • 右移


  • 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0


解析:这三个位运算用的较少,不做过多解释,不过大家可以记住:一个整数左移一位会翻两倍,移动两位翻四倍,如10左移一位变20,移两位变40。向右移动则相反,移动一位缩小一半,以此类推。


3.位运算的技巧(干活)


1.干货一:消去X二进制位的最后一位1


       x=1100(二进制形式)


       x-1=1011


       x&(x-1)=1000            


  x二进制的最后一位1变为了0


2.快速判断是否是2的幂。


  首先我们要明白,如果X是2的幂,如1,2,4,8,16等等


               1.X>0


               2.X的二进制的表示中只可能有一个1


               如果我们利用x&(x-1)去掉x唯一的一个1,则得到结果肯定为0


如果,只要a是2的幂那么得到的结果肯定为0


public class Demo5 {
    public static void main(String[] args) {
       int a=16;
       int b=a&(a-1);
        System.out.println(b);//0
    }
}

3.判断一个数的二进制位有几个1


这是一个高频的考点,同理于上面,如果我们利用x&(x-1)可以去掉最后一位0,我们通过while循环一直除去最后一位0,直到除完以后x变位0,则知道x的二进制位有几位1。


代码演示:


public class Demo5 {
    public static void main(String[] args) {
      int a=345897;
      int count=0;
      while (a!=0){
          a=a&(a-1);
          count++;
      }
        System.out.println(count);//9
    }
}

4.找出重复数组中,唯一一个不重复的数字


题目:在一个数组中,每个数字都出现了两次,只有一个数组出现了一次,请找出这个数字


int[] arr={1,1,2,2,3,4,4,5,5,6,6}


我们通过异或的性质可以很清楚理解:x^x=0  x^0=x


public class Demo5 {
    public static void main(String[] args) {
        int[] arr={1,1,2,2,3,4,4,5,5,6,6};
        int x=0;
        for (int i = 0; i < arr.length; i++) {
            x=arr[i]^x;
        }
        System.out.println(x);//3
    }
}

   第四个是LeetCode的题目,它还有升级版的题目,有兴趣的可以去搜索,在这由于篇幅有限不做叙述。

相关文章
|
存储 算法 C++
C++初阶之一篇文章教会你list(模拟实现)(上)
这个表中列出了C++标准库中list容器的一些成员类型定义。这些类型定义是为了使list能够与C++标准库的其他组件协同工作,并提供一些通用的标准接口。每个成员类型
学C的第八天(完成猜字谜游戏复习之前的内容;了解goto转向语句;补充知识点;练习,学习试除法和辗转相除法)-2
3.写一个代码,打印100-200之间的素数:(新思路:试除法) (判断i是否为素数:用 2到i-1 之间的数字去试除 i,如果能整除则i不是素数)
|
C语言
C语言第十课----------------扫雷----------数组的经典练手题
C语言第十课----------------扫雷----------数组的经典练手题
|
存储 安全 C++
C++初阶之一篇文章教会你list(模拟实现)(下)
4.swap void swap(list<T>& x) { std::swap(_head, x._head); // 交换两个链表的头结点指针 } 这是 list 类的成员函数 swap,它用于交换两个链表的内容。
|
C语言
学C的第八天(完成猜字谜游戏复习之前的内容;了解goto转向语句;补充知识点;练习,学习试除法和辗转相除法)-1
复习之前学C的内容: 猜数字游戏: 1. 电脑会随机生成一个数 2. 猜数字: a> 猜大了,提醒猜大了,继续猜 b> 猜小了,提醒猜小了,继续猜 c> 猜对了,恭喜你,猜对了,结束游戏 3. 玩完一把不过瘾可以继续玩,不用退出程序
离散数学笔记_第一章:逻辑和证明(1)(上)
离散数学笔记_第一章:逻辑和证明(1)(上)
112 0
离散数学笔记_第一章:逻辑和证明(1)(下)
离散数学笔记_第一章:逻辑和证明(1)(下)
121 0
数学知识补充(一)度量空间
数学知识补充(一)度量空间
75 0
|
算法 C语言 Python
01【C语言 & 趣味算法】百钱百鸡问题(问题简单,非初学者请忽略叭)。请注意算法的设计(程序的框架),程序流程图的绘制,算法的优化。
01【C语言 & 趣味算法】百钱百鸡问题(问题简单,非初学者请忽略叭)。请注意算法的设计(程序的框架),程序流程图的绘制,算法的优化。
01【C语言 & 趣味算法】百钱百鸡问题(问题简单,非初学者请忽略叭)。请注意算法的设计(程序的框架),程序流程图的绘制,算法的优化。
(思维)(必要做题步骤)(皮卡丘与 Codeforces )D - 先来签个到
(思维)(必要做题步骤)(皮卡丘与 Codeforces )D - 先来签个到
104 0