c# 位运算符

说来惭愧,今天看别人提供的源码,看了这些运算符竟然有些记不起来,在这里就记录一下,

首先认识这些运算符:

& :按位与,其实与&&逻辑运算符有一致的地方,下面会讲到:

| :按位或,同样与||有类似的地方。

~:按位取反

^:按位异或

<<:左移运算符

>>:右移运算符

需要注意的是上面的运算符都是针对Bit(位)进行的运算符,整数或浮点数使用这些运算符会自动进行二进制的位运算。

下面一个个来剖析。

 

&:

我们直接看示例代码:

c# 位运算符

得到的结果是 :12 ,这个就很有疑问了,我们一点点来看,首先是位运算符会把a和b进行位运算,我们先把两个数转换成二进制:

a  :0000 1101  ,  b: 0000 1110.这两个2进制使用 & 运算符是怎么计算的呢?我们下面来看:

c# 位运算符&运算符会对二进制相同位置上面的0和1进行对比,当相同位置数字相同时就返回这个相同的数,否则就返回0,是不是和&&运算符判断两个bool 一致则返回True,否则返回False类似。所以我们得到了result这个结果,转化成十进制就是12了。

 

| :

下面的代码:

c# 位运算符

得到的结果却是15,同样的,我把 | 计算的二进制结果贴出来:

c# 位运算符其实判断方式是一样的,只是返回的结果不一样, | 运算符判断两个二进制相同位置的0和1,只要其中一个位置的数字是1就返回1,是不是和 || 运算符同样很类似,只要一个True则返True,再把得到的结果转化成10进制就是15了。

^ :

我们还是看代码:

 

c# 位运算符结果:c# 位运算符

为什么是这个结果了,我们看^对两个二进制数的计算,如图:

c# 位运算符 从中可以看出,^ 判断位置上面相同的数字时,如果两个数相同,不论是0还是1都返回0,如果其中一个为1就返回1.而 | 是只要有一个只要位置上一个为1就返回1,所以名字叫异或(不同的返回或)。

 

<< :

还是看代码:

c# 位运算符结果:c# 位运算符

哇,这个结果太不一样了,我们还是看运算的原理图:

c# 位运算符可以看出<<运算符之所以叫左移,其实目的就是把符号左边二进制的位置往左边移动右边设置好的格数(我这边是a移动一格,b移动2格),然后往左移动几格后面就补几个0;所以再把得到的结果转成10进制就得到结果。

 

>> :

看看和<<有什么不同:

c# 位运算符结果:c# 位运算符

看看二进制的运算图:

c# 位运算符可以看出,<<右移运算符就是把二进制位置上的数字往右边移动指定格数,移动几格就在前面补几个0(后面一篇会讲到进制方面的内容),再把结果转化成10进制。

 

~ : 

把这个留着最后因为比较特别还有点复杂,先看代码:

c# 位运算符结果:c# 位运算符

这个是怎么操作二进制的呢,首先要要记住一些原则,就是正数的反码,补码都是其本身的源码负数的反码是符号位不变,本身的0变1,1变0,补码就是反码+1,最后进行补码取反时连同符号位一起变得到的反码就是结果:

c# 位运算符

上图中先进行的负数的按位取反操作,首先得到反码,然后负数的补码操作是反码加1,符号位都不变,然后把得到的补码取反(符号位一起取反),得到的反码就是结果,符号位为0,结果得正。

然后进行正数的取反,首先得到正数的补码(源补码,到了这一步就开始了类似与负数取反的操作),把正数的补码进行取反,得到一个新码,既不是反码也不是补码,当做中间值进行操作,对他进行补码,不同的是负数取反是加1,那么正数取反就是减1,再次变更符号位,得到补码,然后将补码取反,得到的反码就是结果。把得到的结果转成十进制要注意,负数的符号位是不参与计算的。

经过多次实验得到一个规律就是:

~(+a)=  -(a+1);(正数按位取反只需要把当前数加1然后改成负的)

~(-a)=   (+a-1);(负数按位取反只需要把当前数先当做正数,然后减1得到结果)

以上是我对~ 的理解,下篇对进制进行解释,包括二进制,八进制,十进制,十六进制