左移,右移操作符,按位与,按位或,按位异或,取反相关知识

前提所备知识:原码,反码,补码以及二进制

一:在计算机中存的是二进制数,其中二进制数包括无符号整数有符号整数,其中无符号整数的范围为有符号整数的两倍,例如8个比特位中,有符号整数对应-127到127,无符号整数对应0到255

二:一个整数大小为4个字节,也就是32个比特位每1个比特位就对应一个二进制数,也就是说整数1在计算机中二进制表达为00000000000000000000000000000001(总共32位数)。其中第一位数代表符号0代表正数,1代表负数。比如100000……0000001它的第一位是1,所以这个数是负数,0111010……000001它的第一位是0,所以这个数是正数。

三:正数存储在计算机中,原码,反码和补码都是一样的,比如整数13在计算机中,它表示为00000000000000000000000000001101,它的原码,反码,补码都是这个数。

但是负数存储在计算机中,存储的是它的补码

四:负数的原码,反码,补码转换方式如下:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第1张图片

更推荐记法二,因为变换公式一样记得更方便(原码变补码为取反加1,补码变原码也是取反加1)

五:计算机只能运算加法,不能运算减法,(因为计算机只有加法器),所以想要进行减法,其实也就是加上负数罢了

简单复习下前提所备的知识后就可以学习新的知识了

第一:左移操作符<<(箭头向左的是左移)

移动规则:左边抛弃,右边补零

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第2张图片

第二:右移操作符>>(箭头向右的是右移)

移动规则:1.逻辑右移——右边抛弃,左边补零

                   2.算术右移——右边抛弃,左边补符号位的数(如果是正数就补0,负数就补1)

其中根据编译器的不同,而选择逻辑右移或算术右移(但绝大多数的编译器都是算术右移)

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第3张图片

注:不要移动负数位,这个是标准未定义的

例如:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第4张图片

第三:按位与  &

类比:&&是并且,也就是说两真同时为真才为真,&是按位与,也就是说两数相同则为1,不同则为0。例如:一个数是13&5也就是1101&0101,比较对应位的数,得到0111,也就是7,所以13&5==7

第四:按位或 |

类比:||是或者,也就是说两个有一真则为真,|是按位与,也就是说两数有1就为1,没1就为0(因为计算机中1代表真)。例如:一个数是13|5也就是1101|0101,比较对应位的数,得到1101,也就是13,所以13|5==13

第五:按位异或  ^(在数字6上面)

不相同才为1,相同为0。例如:13^5也就是1101^0101,比较对应位的数,得到1000,也就是8,所以13^5==8

公式一:a^a==0

理解:因为两数的二进制数相同,所以对应的每一位的数都相同,相同为0,所以所有都数按位异或后都为0,对应的十进制数也就是0

公式二: 0^a==a

理解:因为0的二进制数是32个0,所以a中有1的位数按位异或0还是1(不相同为1),a中有0的位数按位异或还是0(相同为0)

第六:取反  ~

也就是0变为1,1变为0

注:以上六个操作符的操作数必须是整数

练习1:

一道面试题目:不能创建临时变量(第三个变量),实现两个数的交换。

很容易想到的采用临时变量方法:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第5张图片

当题目做了要求后,那么就需要另寻他法了

另一种方法:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第6张图片

这样也能完成换算,但是会有一个问题,那就是当a和b的数很大的时候,a+b时就有可能溢出整数类型的最大值,所以是有缺陷的

采用位操作符解决的方法:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第7张图片

这样既没有使用临时变量,也没有溢出的缺陷,唯一缺点就是想不到(所以只能多刷题,多看看别人写的代码,积累方法了)

练习2:

编写代码实现:求⼀个整数存储在内存中的⼆进制中1的个数。

类比:要得到1234的每一位的数,一般采用的方法是1234%10=4,再1234/10=123,然后123%10=3,再123/10=12……当到最后一位1时,1/10=0,代表已经是个位数了,所以停止循环。因为1234是十进制的数,所以是%10和/10,因此对于二进制数就是%2和/2

方法一:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第8张图片

但是这样只适用于正数,负数就不行了(例如-1对应的二进制是32个1,但是-1/2==0,不符合实际),所以我们需要稍微修改一下,让int类型转变为unsigned(无符号)类型,这样即使输入-1,也会让-1所对应的有符号二进制数转变为无符号二进制数(即32个1的正数)

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第9张图片

方法二:

思路:用二进制的1一位一位对应上去,直到左移32位变为32个0时,停止,如果对应的数是1,计数器加1

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第10张图片

但是还能更优化,因为这个办法必须循环32次

答案:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第11张图片

方法三:

算法:n=n&(n-1)

举例:

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第12张图片

由例可知,每&一次,说明含有1个1

这个算法就是用来除掉1的

左移,右移操作符,按位与,按位或,按位异或,取反相关知识_第13张图片

你可能感兴趣的:(c语言)