二进制运算——位移运算

位移运算

位移运算是我们既陌生又熟悉的二进制操作。陌生是指不易理解且不常用,熟悉是指“别人家的开发工程师”在代码中经常使用这种方式进行高低位的截取、哈希计算,甚至运用在乘除法运算中。向右位移1位近似表示除以2(如表1-2 所示),十进制的奇数转化为二进制数后,在向右移时,最右边的1将被直接抹去,说明向右移对于奇数并非完全相当于除以2。在左移<<与右移>>两种运算中,符号位均参与移动,除负数往右移动,高位补1之外,其他情况均在空位处补0。

表1-2 带符号位移运算
正数/负数 向左移<< 1位 向右移>> 1位
正数(35的补码0010 0011) 0100 0110 = 70 0001 0001 = 17(近似除2)
负数(-35的补码1101 1101) 1011 1010 = 1(1000101+1)= -70 1110 1110 = 1(0010001 + 1)= -18
正数(99的补码0110 0011) 1100 0110 = -58(正数变负数) 0011 0001 = 49
负数(-99的补码1001 1101) 0011 1010 = 58(负数变正数) 1100 1110 = -50

左移运算由于符号位参与向左移动,在移动后的结果中,最左位可能是1或者0,即正数向左移动的结果可能是正,也可能是负;负数向左移动的结果同样可能是正,也可能是负。

对于三个大于号的>>>无符号向右移动(注意不存在<<<无符号向左移动的运算方式),当向右移动时,正负数高位均补0,正数不断向右移动的最小值是0,而负数不断向右移动的最小值是1。无符号意即藐视符号位,符号位失去特权,必须像其他平常的数字一起向右移动,高位直接补0,根本不关心是正数还是负数。此运算常用在高位转低位的场景中,如表1-3所示分别表示向右移动1~3位的结果,左侧空位均补0。

表 1-3 无符号位移运算
正数/负数 向右移>>>1位 向右移>>>2位 向右移>>>3位
正数(35的补码0010 0011) 0001 0001 = 17 0000 1000 = 8 0000 0100 = 4
负数(35的补码1101 1101) 0110 1110 = 110 0011 0111 = 55 0001 1011 = 27

在实际编程中,位移运算仅作用于整形(32位)和长整型(64)数上,假如在整型数上移动的位数是字长的整数倍,无论是否带符号位以及移动方向,均为本身。因为移动的位数是一个mod 32的结果,即35>>1与35>>33是一样的结果。如果是长整型,mod 64,即35<<1与35<<65的结果是一样的。负数在无符号往右移动63位时,除最后边为1外,左边均为0,达到最小值1,如果>>>64,则为其原数值本身。

猜你喜欢

转载自blog.csdn.net/weixin_43222122/article/details/104299203