- Java王者归来:从入门迈向高手
- 洪锦魁
- 1258字
- 2025-02-17 16:14:32
4-6 位运算
在程序设计时,为了方便通常使用十进制方式表达数字,其实在计算机内部是使用二进制方式表达数字,也就是0或1,存储这个数字的空间称为位(bit),这也是最小的计算机内存单位。
例如,若是以Byte数据类型,占据8位空间,可以用下图方式表达。

如果十进制数字是6,表达方式如下。

从3-2-1节可知Byte数据最大值是127,它在内存空间的表达方式如下。

其中,最左边的位代表正值或负值,有时候也可以称为正负号。当此位是0时代表这个空间是正数,当位是1时代表这个空间是负数。
二补码就是将数字由正值转换为负值(或是由负值转换为正值)的运算方式,基本概念是在二进制表达的数字中,将每个位进行反向(将0转1或是将1转0)运算,然后将结果加1。例如,Byte整数的1表达方式如下。

下列是求-1的计算过程(二补码),首先反向运算后结果如下。

将上述结果加1后结果如下,下列就是-1的表达方式。

注 以上规则的例外是0和-128。
从3-2-1节可知,Byte数据最小值是-128,它在内存空间中表达方式如下。

下列是Byte数据从最大值到最小值的内存空间表示法。

其实以上概念可以扩展到int、short或long类型的数据。
程序实例ch4_22.java:验证上述Byte数据在127~-128的二进制表示法,需留意的是当表达负数时,在0b前方要加上(byte),可参考第12、14、16行,这是强制将0b11111111整数int转成Byte。4-8节中将更进一步说明(byte)的意义。

执行结果

Java位运算示例如下。

4-6-1 ~运算符
这个运算符相当于是将位执行not运算,也就是如果位是1则改为0,如果位是0则改为1。程序实例ch4_23.java:~运算符的应用,整个结果说明如下:
第4、5行~i结果是:10000000=-128
第6、7行~i 结果是:11111110=-2
第8、9行 ~i结果是:11111111=-1
第10、11行~i结果是:00000000= 0
第12、13行~i结果是:01111110= 126
第14、15行~i结果是:01111111=-127

执行结果

4-6-2 位逻辑运算符
4-5-4节有介绍过逻辑运算符,本节主要是将此逻辑运算的规则应用在二进制系统的位上。程序实例ch4_24.java:位逻辑运算符的应用。
第6行x&y结果是:00000001=1
第7行x|y结果是:00000101=5
第8行x^y 结果是:00000100= 4

执行结果

4-6-3 位移位运算符
基本上有三种位移位方式,特点是不论是byte或short整数数据在执行位移位前都会被自动转换为32位整数,语法格式如下。
operand 移位运算符 operand
左边的操作数是要处理的数据,右边的操作数是移位的次数。下列是三种位移位方式。
1.位左移<<
在位左移过程中最右边的位会用0递补,所以位左移有将数字乘以2的效果,但是需留意,如果位左移过程中更改最左边的位也可称正负号,则数字乘2的效果将不再存在。
程序实例ch4_25.java:验证byte数据在执行位移前被自动转换为32位整数。

执行结果

如果x仍是byte数据,则获得的结果是0b10001010,结果将是-118,但是因为在执行位移前被自动转换为32位整数,所以得到138的结果。第6、7行则是使用byte和int数据类型测试y和z变量数据获得的结果。
程序实例ch4_26.java:位左移的应用。
第6行x值是00000000…00000101=5
第7行移位结果是00000000…00001010=10
第8行移位结果是00000000…00010100=20
第9行y值是00100000…00000001=536870913
第10行移位结果是01000000…00000010=1073741826
第11行移位结果是10000000…00000100=-2147483644(正负号变动)
第12行移位结果是00000000…00001000=8(正负号变动)

执行结果

2.位右移>>
位右移时左边空出来的位均补上原先的位值,所以位右移时将不会改动到原先的正或负值。程序实例ch4_27.java:>>运算符的应用,位右移时最左位不变的应用。
第6行x值是00000000…00000101=5
第7行移位结果是00000000…00000010=2
第8行移位结果是00000000…00000001=1
第9行y值是11111111…11111000=-8
第10行移位结果是11111111…11111100=-4
第11行移位结果是11111111…11111110=-2
第12行移位结果是11111111…11111111=-1

执行结果

3.位右移>>>
位右移时左边空出来的位会补上0,所以如果原先是负值的数字,经过处理后将变为正值。
程序实例ch4_28.java:>>>运算符的应用,位右移时最左位补0的应用。
第6行x值是00000000…00000101=5
第7行移位结果是00000000…00000010=2
第8行移位结果是00000000…00000001=1
第9行y值是11111111…11111000=-8
第10行移位结果是01111111…11111100=2147483644
第11行移位结果是01111111…11111110=1073741822
第12行移位结果是01111111…11111111=536870911

执行结果

4-6-4 位运算的复合指定运算符
4-4节复合指定运算符的概念也可以应用在本节的位运算符。

程序实例ch4_29.java:复合指定运算符在位运算中的应用。

执行结果
