Java 中的“位”操作符 计算机中最小的单位是“位”(bit)。位的取值只能是 0 或 1。 Java 中有“两种”直接对“位”进行运算的操作符:按位操作符、移位操作符。 注意:Java 中的位操作符只用于 int 类型的数据。byte、short、char 类型的数据也可以使用位操作符,但在操作之前会被自动转为 int 类型,返回的结果也是 int 类型。(int 为四字节,byte 为一字节,short、char 为 二字节) 按位操作符 按位操作符有四个:按位与 按位或 按位异或 按位取反 按位与:两个输入位都为 1 ,得到一个输出位 1,否则得到一个输出位 0。 1&1=1,1&0=0,0&1=0,0&0=0。 按位或:两个输入位只要有一个为 1 ,得到一个输出位 1,否则得到一个输出位 0。 1|1=1,1|0=1,0|1=1,0|0=0。 按位异或:两个输出位一个为 0 一个为 1,得到一个输出位 1,否则得到一个输出为 0。按位异或也可以理解为“不进位的按位相加”。 1^1=0,1^0=1,0^1=1,0^0=0。 自己与自己按位异或等于 0; 与 0 按位异或等于自身; 按位异或满足交换律:a^b = b^a。(以“不进位的按位相加”更好理解。) 按位取反:一操作符,输入位为 0,输出位为 1,或,输入位为 1,输出位为 0。 ~1=0,~0=1。 在实际代码中, 会输出 -2, 会输出 -1。这是因为: x + (~x) = 0b1111 1111, x + (~x) + 1 = 0b0000 0000 = 0, 因此,~x = -x – 1。 以 1 为例,int 类型的 1 的二进制为 0b0000 0001,取反后为 0b1111 1110,这正是 int 类型的 -2 的二进制; 以 0 为例,int 类型的 0 的二进制为 0b0000 0000,取反后为 0b1111 1111,这正是 int 类型的 -1 的二进制。计算机内部用补码来表示负数,即,将负数的绝对值的二进制按位取反再加一。以一个字节为例,2 的二进制为 0b00000010,则 -2 = 0 – 2 = 0b00000000 – 0b00000010 = 0b00000001 + 0b – 0b00000010 = 0b00000001 + 0b = 0b,即 -2 的二进制为 0b。 正负数相加时,补码的优势就显现出来了:2+(-2) = 0b00000010+0b = 0b00000000 = 0。 Java 支持 、 和 。(由于 ~ 为一操作符,所以不支持 。) 移位操作符 移位操作符有三个:左移位操作符 “有符号”右移位操作符 “无符号”右移位操作符 左移位操作符:向左移位,低位补 0。 以一个字节为例: 2<<1 = 0b00000010<<1 = 0b00000100 = 4; 2<<2 = 0b00000010<<2 = 0b00001000 = 8; -(2<<1) = -(0b00000010<<1) = -(0b00000100) = -4; (-2)<<1= (0b)<<1 = 0b = -4; 左移一位相当于乘以 2,左移两位相当于乘以 4,以此类推。 注意:当数字较大,或左移位数较多时,要特别当心。例如,(2^31-1)<<1 = -2,这是因为 Java 中的 int 类型占用四个字节,(2^31-1) 表示为 0b0111……1111,向左移动一位后,变为了 0b111……1110,与 -2 的表示相同,Java 将其识别为了-2。(无符号类型 char 不会遇到这种情况) “有符号”右移位操作符:向左移位,若为正数,高位补 0,若为负数,高位补 1。 以一个字节为例: 2>>1 = 0b00000010>>1 = 0b00000001 = 1; 2>>2 = 0b00000010>>2 = 0b00000000 = 0; -(2>>1) = -(0b00000010>>1) = -(0b00000001) = -1; (-2)>>1= (0b)>>1 = 0b = -1; “有符号”右移一位相当于除以 2(向下取整),“有符号”右移两位相当于除以 4(向下取整),以此类推。 “除以 4,向下取整”与“除以 2,向下取整,再除以 2,再向下取整”两者完全等价。 正数经过有限次的“有符号”右移后,最终都将变为 0;负数经过有限次的“有符号”右移后,最终都将变为 -1。 “无符号”右移位操作符:向左移位,高位补 0。 当两个很大的正数相加,且相加后最高位等于一,求它俩的平均数(除二取整),这时候不能用 >>(因为右移后最高位会补一),而应该用 >>>(最高位补零)。 Java 支持 、 和 。 位操作符的常见用法 1 交换整数 a 和 b 的值的方法: 2 对一个整数的二进制“重复两次”按位取反后加一,得到其本身:~(~a+1)+1 = a+(~1)+1 = a。 3 :一个整数与自己的相反数按位与。 作用:二进制下最后出现(最右侧)的 1 保持不变,其余都置为 0,也即提取出二进制下最右侧的 1。例如: 原数:0b 相反数就是数按位取反后再加一。 取反:0b0 加一:0b0 按位与:
证明: 如果 x 是奇数,那二进制下最后一位肯定是 1,如果用 a 表示一串任意的 0110…1001,那 x 的二进制可以表示为 a1,-x 的二进制可以表示为 ~(a1)+1=(~a)0+1=(~a)1,于是 x&(-x)=a1&(~a)1=00…001,得证。 如果 x 是偶数,那 x 的二进制可以表示为 a100…00,-x 的二进制可以表示为 ~(a100…00)+1=~(a)011…11+1=~(a)100…00,于是 x&(-x)=a100…00&(~a)100…00=00…00100…00,得证。 4 :一个整数减一,然后与自身按位与。 作用:二进制下最后出现(最右侧)的 1 置为 0,其余保持不变。 证明: 如果 x 是奇数,那二进制下最后一位肯定是 1,如果用 a 表示一串任意的 0110…1001,那 x 的二进制可以表示为 a1,x-1 的二进制可以表示为 a0,于是 x&(x-1)=a1&a0=a0,得证。 如果 x 是偶数,那 x 的二进制可以表示为 a100…00,x-1 的二进制可以表示为 a011…11,于是 x&(x-1)=a100…00&a011…11=a000…00,得证。 用途:判断一个正整数是否为 2 的 n 次方。 1 的二进制 1; 2 的二进制 10; 4 的二进制 100; 8 的二进制 1000; 2 的 n 次方有一个共同点,它们的二进制最左侧为 1,其它都为 0。如果 x&(x-1)=0,那它必是2 的 n 次方。 用途:求一个正整数对应二进制数中包含的 1 的个数。 每进行一次 x&(x-1),右侧就少一个 1。 其它 Python 中也有相同的“位”操作符:按位与 按位或 按位异或 按位取反 左移位操作符 “有符号”右移位操作符 用法与 Java 完全一样。 Python 中没有“无符号”右移位操作符。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/84479.html