Java位操作

本文详细解释了计算机存储方式中的补码概念,并深入探讨了位操作符如与、或、异或及非操作的基本用法,以及位移操作的特性。通过实例演示了如何使用位操作解决问题,并介绍了补码在计算机加法运算中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

补码

在说位操作之前,还是要把计算机里面怎么存储来简单说下。补码有两条规则:

1、大于0:补码与原码相同。

2、小于0:符号位(最高位)为1,其他为绝对值的原码取反后加一。

比如来看-1的补码怎么得到:

1、绝对值的原码为:0x00000001

2、最高位设置1,得到:0x80000001

3、其他位取反得到:0xfffffffe

4、加一得到:0xffffffff

好了,为什么要这么纠结地搞出来一个补码?

正是因为有了补码形式,计算机的世界里面是没有减法的,其实容易看到如果把补码看成是一个正数,其值为:2^32-X,那么:

a、负数相加:(2^32 - X) + (2^32 - Y) = (2^32 - (X + Y)) + 2^32,那么如果X + Y没有溢出的话,这值显然表示的是-(X + Y)的补码。

b、正数加负数:X + (2^32 - Y) = 2^32 - (Y - X),如果X < Y,那么结果就是X - Y的补码,否则,X + (2^32 - Y) = 2^32 + (X - Y),结果就是X - Y的原码。

c、正数加正数:略。

那么从上面的这三种情况就知道为什么计算机中没有减法了。


与操作:

首先来介绍最简单的操作符:与,作用是在两个操作数的相同位都为1时,结果中对应位才为1。比如在检查int型x第三位是否为1时,可以这么写:

        if ((x & 8) == 8) {
            // TODO
        }
这里前面为什么要加括号?原因很简单:位操作的优先级是很低的,如果不加括号会先运行8 == 8的比较~

上面这种用处当然是&用到最多的地方,其实(x&8)还有另外的一层意思:把第三位之外的其他位都清零,还有另一个种情况,你想把第1位设置为0时可以x&0xfffffffe。那么&还有没有其他有意思的作用呢?比如下面这段代码:

System.out.printf("%x", (x & (-x)));
用一行代码就可以算出x中不为0的最低位是多少,这个方法还是挺有用的,在很多优化的时候都会用到。同样实现该功能的另一种写法是:
System.out.printf("%x", (x & (1 - x)));


或操作:

或操作的含义是,只要操作数中有一个为1,那么结果中对应位则为1。同与操作,或操作也可以用来检查x的某一位是否为1,比如检查第三位,如下:

        if ((x | 8) == x) {
            // TODO
        }

因为(x|8)的含义是,如果x第三位为1,那么保持不变,如果x第三位为0,那么变成1。或操作最大的用处就是将某位设置为1.


异或操作:

异或操作的含义是:两个操作数对应位置同为0或同为1时,结果中对应位为0,否则,结果中对应位为1。由其定义看到x^x = 0,那么用异或就可以很简单地解决下面这个问题了:

有N个数,其中只有一个数字出现的次数是奇数次,其他数字出现的次数都是偶数次,如何找到出现奇数次的数字?

把所有的数字全部异或的结果就是要找的数字了~

在接触异或时,感觉他比较神奇的地方是在博弈上的用法,一个最简单的例子:

有N堆石子,A和B轮流从其中的一堆石子中拿走任意个(当然不能超过这堆石子的总数),问:什么情况下,先手可以必胜?

大家从有两堆石子的情况下考虑一下应该能猜到:这N堆石子异或的结果不为0时先手必胜(博弈问题就此打住)~


非操作:

非操作的含义是:如果原来为1,那么结果中对应位为0,如果原来为0,那么结果中对应位为1。非操作是单操作数运算符,算是最简单的一个位操作了。


位移:

在Java中的位移有三种:

1、<<:左移,最右边用0补充。

2、>>:右移,最左边用符号位补充。

3、>>>:无符号右移,最左边用0补充。

首先,不要以为右移等价于除2(虽然大部分用到的时候是等价的)!比如:

System.out.println(1 >> 32);

这段代码你的预期结果是0,但实际上,输出是1,为什么会这样呢?在int移位的时候,1>>x实际上执行的是1>>(x%32),那么1>>32也就是相当于1>>0,没有移动。那么上面怎样就变成0了?如下:

System.out.println(1L >> 32);
输出为0,long对应执行的是1L>>(x%64)。大家最开始接触位移应该是遇到:

01字符串与int之间的相互转化~

这样类似的问题。位移中需要注意的地方的话就上面这个,其他的就没什么了~

END。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值