位运算及移位,反码,补码

反码,补码

将正数各个位取反,1变为0,0变为1所得二进制位反码,将反码+1所得到的二进制数为补码,补码为该正数在计算机中存储的负数形式,如,4在int类型占用4个字节32位,其原码,反码及补码如下

原码:00000000 00000000 00000000 00000100
反码:  11111111 11111111 11111111 11111011
补码: 11111111 11111111 11111111 11111100  (-4在计算机中的表示形式)

通过代码验证-4的二进制形式与上述补码一致

String binaryString = Integer.toBinaryString(-4);
System.out.println(binaryString);

无符号正数与有符号整数

无符号整数的所有位均表示数字,有符号整数的最高位表示符号,1表示负数,0表示正数。

对于byte,无符号时最小值为00000000=0,最大值为11111111=2^7+2^6+ ... 2^0=255,包含256个数字,有符号时,最小值为10000000=-2^7=-128,最大值为01111111=2^6+2^5+ ... 2^ 0=127

位运算

& 按位与,全为1时为1,否则为0

|  按位或,全为0时为0,否则为1

~ 按位非,0求非为1,1求非为0

^ 按位异或,相同为0,不同为1

示例(某些示例只显示的计算位,准确应该是32位,且以下示例也都可以通过java代码来验证结果是否正确)

1、& 按位与,全为1时为1,否则为0

3 & 5 = 0011 & 0101 = 0001 = 1
6 & 5 = 0110 & 0101 = 0100 = 4
7 & 5 = 0111 & 0101 = 0101 = 5

2、| 按位或,全为0时为0,否则为1

3 | 5 = 0011 | 0101 = 0111 = 7
6 | 5 = 0110 | 0101 = 0111 = 7
7 | 5 = 0111 | 0101 = 0111 = 7

3、~ 按位非,0求非为1,1求非为0

~ 2 = ~ 00000000 00000000 00000000 00000010 = 11111111 11111111 11111111 11111101

这是一个负数,不好直接计算,正数的负数形式是先反码然后+1得到反码即为该正数的负数形式,反过来,负数获取其对应正数,先-1,然后反码

~2-1 = 11111111 11111111 11111111 11111100

取反

00000000 00000000 00000000 00000011 = 3

所以~2 = -3

同理可得到~3=-4

4、^ 按位异或,相同为0,不同为1

2 ^ 3 = 0010 ^ 0011 = 0001 = 1
3 ^ 3 = 0011 ^ 0011 = 0000 = 0 
4 ^ 7 = 0100 ^ 0111 = 0011 = 3

移位

1、左移,高位移除,低位补0

2 << 3 = 0010 << 3 = 0010 000 = 2^4=16

左移一位,相当于乘以2,左移n位,相当于乘以2的n次方

对于int类型,当移动超过了32为,相当于移动了movenNum%32位

对于long类型,若移动超过64位,相当于移动了moveNum%64位

byte和short类型,自动把这些类型扩大为int

2、右移,符号位不变,低位移除,高位补符号位

2 >> 2 = 0010 >>2 = 0000=0

右移一位,相当于除以2,左移n为,相当于除以2的n次方,但当移位之后的数值小于1时,实际移位得到的值为0,如上述2 >> 2,2 /2/2=0.5<1,最后结果为0

3、无符号右移,低位移除,高位补0

对于正数的无符号右移,与有符号右移得出的结果一样

System.out.println(8 >>> 2); // 2
System.out.println(8 >> 2); // 2

负数的无符号右移与有符号右移得出结果不同

/*
         * 1的原码,反码及补码如下
         * 原码:00000000 00000000 00000000 00000001
         * 反码:11111111 11111111 11111111 11111110
         * 补码:11111111 11111111 11111111 11111111 (-1)
         * 
         * 11111111 11111111 11111111 11111111 
         * 有符号右移两位,低位1去掉,高位补1,最后二进制码跟之前一样,结果还是-1
         * 11111111 11111111 11111111 11111111 
         * 无符号右移2为得到00111111 11111111 11111111 11111111
         * 该值通过2^29+2^28+ ... 2^0计算得出结果为1073741823
         */
        System.out.println(-1>>2); // -1
        System.out.println(-1>>>2); // 1073741823

 4、不存在无符号左移,因为左移时,低位补0,高位直接舍弃,不需要对符号位添加1或者0操作,在java代码中,如下写法会出现编译错误

猜你喜欢

转载自www.cnblogs.com/qq931399960/p/10795133.html
今日推荐