java位运算及移位运算你还记得吗

打印 上一主题 下一主题

主题 905|帖子 905|积分 2715

本文中所提到的运算都是基于整数来说的,因为只有整数(包括正数和负数)在操作系统中是以二进制的补码形式运算的,关于原码、反码、补码、位运算、移位运算的背景这里不再介绍,网上资料很多,感兴趣的可自行搜索。
java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。
数据类型字节数二进制位数表示范围默认值byte18-2^7 -- 2^7-10char2160 -- 2^16-1'\u0000' (代表字符为空 转成int就是0)short216-2^15 -- 2^15-10int432-2^31 -- 2^31-10long864-2^63 -- 2^63-10L原码、反码、补码

使用位运算前需要先弄清楚这几个概念
原码

原码也叫机器码,整数的二进制形式表示,最高位为符号位。1表示负数,0表示正数,除去符号位后剩余其他的所有位是该整数的绝对值的二进制值。
  1. int a = 7; //原码二进制表示为:00000000 00000000 00000000 00000111
  2. int b = -7;//原码二进制表示为:10000000 00000000 00000000 00000111
复制代码
反码

反码需要区分是正数还是负数,正数的反码跟原码相同,负数的反码是除符号位外,其他位取反(即负数的最高位是1不变,其他位0变成1,1变成0)。
  1. int a = 7; //反码二进制表示为:00000000 00000000 00000000 00000111
  2. int b = -7;//反码二进制表示为:11111111 11111111 11111111 11111000
复制代码
补码

补码也需要区分是正数还是负数,正数的补码跟原码相同,负数的补码是反码最低位加1。
  1. int a = 7; //补码二进制表示为:00000000 00000000 00000000 00000111
  2. int b = -7;//补码二进制表示为:11111111 11111111 11111111 11111001
复制代码
说完了概念,其实这里的原码是方便给人看的,对于计算机运算来说都是使用补码形式操作。以下的位运算和移位运算都是基于补码进行的。
位运算

位运算术语解释

位运算符含义解释备注&按位与两个整数按位对齐,当对齐的两位同时为1则结果为1,否则为0|按位或两个整数按位对齐,当对齐的两位只要有一个为1则结果为1,否则为0~按位非只能适用于一个整数的自身操作,按位取反,即1变成0,0变成1单目运算符^按位异或两个整数按位对齐,当对齐的两位相同时为0,否则为1位运算示例

我们以上面的int a = 7和int b = -7举例位运算的操作。
a的补码二进制为:00000000 00000000 00000000 00000111
b的补码二进制为:11111111 11111111 11111111 11111001
1、a&b
  1. 按位与的结果补码为:00000000 00000000 00000000 00000001
  2. 因为最高位为0,所以为正数,`正数的原码反码补码都相同`,所以原码也为:
  3. 00000000 00000000 00000000 00000001
  4. 转换成十进制的结果就是1。
复制代码
2、a|b
  1. 按位或的结果补码为:11111111 11111111 11111111 11111111
  2. 最高位为1,所以是负数。
  3. 反码=补码-1,得到反码:11111111 11111111 11111111 11111110
  4. 原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000001
  5. 由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是1,所以最后按位或的结果就是-1。
复制代码
3、a^b
  1. 按位或的结果补码为:11111111 11111111 11111111 11111110
  2. 最高位为1,所以是负数。
  3. 反码=补码-1,得到反码:11111111 11111111 11111111 11111101
  4. 原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
  5. 由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。
复制代码
4、~a
  1. 取反结果(补码形式):11111111 11111111 11111111 11111000
  2. 最高位为1,所以是负数。
  3. 反码=补码-1,得到反码:11111111 11111111 11111111 11110111
  4. 原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00001000
  5. 由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是8,所以最后按位或的结果就是-8。
复制代码
5、~b
  1. 取反结果(补码形式):00000000 00000000 00000000 00000110
  2. 最高位为0,所以是正数。正数的原码反码补码都相同,所以转换成十进制结果为6。
复制代码
位运算应用于boolean操作

&(与)、|(或)这两个位运算适用于boolean判断,在这两个运算符的前后的条件都会计算,不像java里的条件判断符&&(并且) ||(或者)会短路,判断符之前的满足条件后,那么判断符之后的表达式不再计算。
  1. public static void main(String[] args) {
  2.     int a = 5;
  3.     if (a < 0 & a++ > 0) {
  4.     }
  5.     System.out.println("&条件后a=" + a);
  6.     if (a > 0 | a++ > 0) {
  7.     }
  8.     System.out.println("|条件后a=" + a);
  9.     if (a < 0 && a++ > 0) {
  10.     }
  11.     System.out.println("&&条件后a=" + a);
  12.     if (a > 0 || a++ > 0) {
  13.     }
  14.     System.out.println("||条件后a=" + a);
  15. }
复制代码
输出结果为:
  1. &条件后a=6
  2. |条件后a=7
  3. &&条件后a=7
  4. ||条件后a=7
复制代码
第一个判断a < 0 & a++ > 0前一个判断已经是false了,但是使用&连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于6。
第二个判断a > 0 | a++ > 0前一个判断已经是true了,但是使用|连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于7。
第三个判断a < 0 && a++ > 0前一个判断已经是false了,使用&&连接的不会再计算后一个表达式的值,所以a的值不变。
第四个判断a > 0 || a++ > 0前一个判断已经是true了,使用||连接的不会再计算后一个表达式的值,所以a的值不变。
移位运算

移位运算术语解释

移位运算符含义解释</tdtd左移/tdtd补码高位(不包括符号位)去掉指定位数,然后剩下的位数整体向左移动指定位数,低位使用0补齐/td/trtrtd>右移补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位补上符号位(即正数补0,负数补1)>>>无符号右移这个主要是针对于负数来说的,补码低位去掉指定位数,然后剩下的位数整体向右移动指定位数,高位(包括符号位)全部补上0移位运算也是基于补码来操作的,因为是采用二进制,所以左移n位相当于该数乘以2的n次方、右移及无符号右移n位相当于该数除以2的n次方,但是无符号右移是相对于负数来说的,把符号位和其他高位都置为0。
移位运算示例

我们仍以上面的int a = 7和int b = -7举例移位运算的操作。
a的补码二进制为:00000000 00000000 00000000 00000111
b的补码二进制为:11111111 11111111 11111111 11111001
1、a2
  1. 符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
  2. 补码:00000000 00000000 00000000 00011100
  3. 高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:28
复制代码
3、a>>>2
  1. 符号位为0,正数,则符号位不变,低位去掉两位,整体右移两位,高两位补0,结果为:
  2. 补码:00000000 00000000 00000000 00000001
  3. 高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1
复制代码
4、b2
  1. 符号位为0,正数,低位去掉两位,整体右移两位,高两位(包括符号位)补0,结果为:
  2. 补码:00000000 00000000 00000000 00000001
  3. 高位为0即正数,正数的原码反码补码相同,所以原码=补码,转换为十进制结果为:1
复制代码
6、b>>>2
  1. 符号位不变,高位去掉两位,整体左移两位,低两位补0,结果为:
  2. 补码:11111111 11111111 11111111 11100100
  3. 高位为1即负数
  4. 反码=补码-1,得到反码:11111111 11111111 11111111 11100011
  5. 原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00011100
  6. 由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是28,所以最后按位或的结果就是-28。
复制代码
移位运算注意事项

1、byte、short、char类型的整数再移位操作时会自动向上转为int类型后再操作移位。
2、int类型占32位,long类型占64位,当对这两个类型移位超出位数时,相当于对要移动的位数取余再移位,例如a1并判断1的个数是否加1,直到这个数的值变为0为止。
5、其他应用场景可自行探索(* ̄︶ ̄)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表