![Java王者归来:从入门迈向高手](https://wfqqreader-1252317822.image.myqcloud.com/cover/394/27563394/b_27563394.jpg)
4-6 位运算
在程序设计时,为了方便通常使用十进制方式表达数字,其实在计算机内部是使用二进制方式表达数字,也就是0或1,存储这个数字的空间称为位(bit),这也是最小的计算机内存单位。
例如,若是以Byte数据类型,占据8位空间,可以用下图方式表达。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_757910.jpg?sign=1739299199-3na9BGOm1X8vLaSLydx7uEXWiE7ioR6b-0-9df7af28c142b65dd63c8cb2bf1d597e)
如果十进制数字是6,表达方式如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_528981.jpg?sign=1739299199-nokaoQbqPFLrHnWXv5V80ooadndA0X5X-0-e409c6afbcf2ad5766b7b16c9d8a2828)
从3-2-1节可知Byte数据最大值是127,它在内存空间的表达方式如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529033.jpg?sign=1739299199-osTxsPlxvTgdHEfISL8RrxHJAVretowc-0-1c0a00f6279a7cf2183c58d97e8ccaf2)
其中,最左边的位代表正值或负值,有时候也可以称为正负号。当此位是0时代表这个空间是正数,当位是1时代表这个空间是负数。
二补码就是将数字由正值转换为负值(或是由负值转换为正值)的运算方式,基本概念是在二进制表达的数字中,将每个位进行反向(将0转1或是将1转0)运算,然后将结果加1。例如,Byte整数的1表达方式如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_757925.jpg?sign=1739299199-wjrEd33BvlJAOnMSOtzTIWNSgAy7A5xO-0-cc8e6037182f960e5fe53d41f248bdef)
下列是求-1的计算过程(二补码),首先反向运算后结果如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529147.jpg?sign=1739299199-cZgoGPJLb7KKXCQjokqMfca3mkTucIqM-0-a4438c426a0efd69f561718a2cd1e19a)
将上述结果加1后结果如下,下列就是-1的表达方式。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529199.jpg?sign=1739299199-Uf84nXLD9RLKbbY9oyDl8QqoS7dWTcDr-0-a22f5635c10c219c345358e3baec79a7)
注 以上规则的例外是0和-128。
从3-2-1节可知,Byte数据最小值是-128,它在内存空间中表达方式如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529254.jpg?sign=1739299199-9LnbCxFk4rVCfrTrlSOT9nE2MWKHUkFO-0-45beb790e68f1fadcb6f6b023612e558)
下列是Byte数据从最大值到最小值的内存空间表示法。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529256.jpg?sign=1739299199-UwVHViVdObhxCrGEYDNGJXsORGeLiF2n-0-7e989f04a85205ddd312e0e32c3dfc9d)
其实以上概念可以扩展到int、short或long类型的数据。
程序实例ch4_22.java:验证上述Byte数据在127~-128的二进制表示法,需留意的是当表达负数时,在0b前方要加上(byte),可参考第12、14、16行,这是强制将0b11111111整数int转成Byte。4-8节中将更进一步说明(byte)的意义。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529259.jpg?sign=1739299199-6zQbcWq1QLA4Ncq6DUVoylekgxbtQ1dC-0-1535931941c243be759759beb6a25dd4)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P53_529265.jpg?sign=1739299199-VUNUD6HQRWhj15mMe46An2XH1PEGmOkc-0-2a509969681ba9f674f938c5c0c23e8a)
Java位运算示例如下。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-T54_757926.jpg?sign=1739299199-gzPr4KC0yZeoJwvoFkvgy6XuyYXshFYs-0-4e357bbf07667c1fc6e78c8e9963c748)
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
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P54_529859.jpg?sign=1739299199-lAufc0ZoVgNcf4dERA7zlWKaevkL5ORC-0-71265f52370d6f98da8fbfa290bff5ac)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P54_529865.jpg?sign=1739299199-RKhFi0DKFetJk9lxGAx8xKjbg6Pfvkas-0-f20fe794b8f3146385d4832a1d0ec7bd)
4-6-2 位逻辑运算符
4-5-4节有介绍过逻辑运算符,本节主要是将此逻辑运算的规则应用在二进制系统的位上。程序实例ch4_24.java:位逻辑运算符的应用。
第6行x&y结果是:00000001=1
第7行x|y结果是:00000101=5
第8行x^y 结果是:00000100= 4
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P54_529869.jpg?sign=1739299199-TZM3pXFctWgJFG4NyUXvYeMTLpURjrCP-0-6357e4949dea1ac05365aa2aaf2568da)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P54_529875.jpg?sign=1739299199-4IyeKgxozDrChnab7vAHa82jbaOOJksc-0-0988816d0b3dc6b1cc7c40cd4f453844)
4-6-3 位移位运算符
基本上有三种位移位方式,特点是不论是byte或short整数数据在执行位移位前都会被自动转换为32位整数,语法格式如下。
operand 移位运算符 operand
左边的操作数是要处理的数据,右边的操作数是移位的次数。下列是三种位移位方式。
1.位左移<<
在位左移过程中最右边的位会用0递补,所以位左移有将数字乘以2的效果,但是需留意,如果位左移过程中更改最左边的位也可称正负号,则数字乘2的效果将不再存在。
程序实例ch4_25.java:验证byte数据在执行位移前被自动转换为32位整数。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P55_530282.jpg?sign=1739299199-h0MLeuMdv8sSKuk1fReuUwrOuqHylyvd-0-6420444c0a7fbe1a1c3981e32484fd2e)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P55_530288.jpg?sign=1739299199-fem114KpKgQkvwGylUIm638UwDloijFs-0-218ee4c37909db622219a5909244c672)
如果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(正负号变动)
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P55_530291.jpg?sign=1739299199-qmJ98gWLgxbppbr2akdn5DUHtS6kau2l-0-c9592e5a13c75275dcf65c3a6a7a457c)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P55_530297.jpg?sign=1739299199-0jKj0rgY4fuSpSmmKhnBrse2XQYDsEZB-0-a36496daf1cf3d76b22ec0996c9c1140)
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
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P56_530707.jpg?sign=1739299199-3hRvJiXiuFpjL76tj1tHgtQSPacjEOk1-0-b3f132e70f571c262fcee0971df9c032)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P56_530713.jpg?sign=1739299199-uRkxM76Mt4UHR7Us1ExY9DYGJJzGzC2H-0-c1be5b624d3312212bb859455c7eddf1)
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
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P56_530716.jpg?sign=1739299199-BoQRajAJlTwKe5bZElsRKTgx6Y0ZkJTe-0-75ea248eb05a2a679808a529e3443506)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P56_530722.jpg?sign=1739299199-47jdl1Vent740bPsiTQmAD6c44Nh9Vcq-0-507343db3918f4808c4870229700a854)
4-6-4 位运算的复合指定运算符
4-4节复合指定运算符的概念也可以应用在本节的位运算符。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-T56_757937.jpg?sign=1739299199-amlyKuVztdTIHmibdwjaU4oGKGxvahQX-0-e5483a7dbc3778b5c5c6cfb1e8f2235a)
程序实例ch4_29.java:复合指定运算符在位运算中的应用。
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P57_531299.jpg?sign=1739299199-DC379JXwsCOosMoUhGMh3Iyi7bz3Ehum-0-d39b5283177aa1162a157be4578aad52)
执行结果
![](https://epubservercos.yuewen.com/9E44AA/15825993204148006/epubprivate/OEBPS/Images/Figure-P57_757938.jpg?sign=1739299199-bPT3FrocK61fygNnMaQF5IHnnhGylC1H-0-677a6a5fea7fbde0fef5e3530ae35f8e)