Java位运算和相关应用&剑指offer不用加减乘除做加法

1. Java中的移位运算

有两个符号移动——

  符号左移:<<

  符号右移:>>

这字面理解就是,带符号位的移动咯,左移很容易理解,空出来的低位补0就好,效果相当于乘以2

主要要区分的是——符号右移>>   和    无符号右移>>>

符号右移——

  保留符号位,然后右边数值位空出来的用符号的那个  值  来补

无符号右移——不管左侧最高位是1还是0,左侧补上的空位统统用0填充

  比如10111110 10001010  10000000 00000000,他是多少我们就不理了

  

  我们右移29位,也就是101后面的都被移掉了;

  如果是无符号右移>>>:00000000 00000000 00000000 00000101——结果是5

  如果是符号右移>>:11111111 11111111 11111111 11111101——结果是-3

这里顺便复习下,Java中的负数用的是补码——

正数的补码 = 原码

负数的补码 = {原码符号位不变} + {数值位按位取反后+1}    or = {原码符号位不变} + {数值位从右边数第一个1及其右边的0保持不变,左边安位取反}

所以这个数字相当于是10000000 00000000 00000000 00000011=-3

所以一共——符号左移,符号右移还有个无符号右移,符号左移直接补0没毛病,符号右移保留符号位,空出来的数值位用符号位的值来补,无符号右移直接补0;

2. 剑指offer的不用加减乘除法做加法

 
一看就是要用到位运算,但不好意思不会哦哈哈哈
要知道几个东西:
    1. 两个数直接进行异或操作,相当于不考虑进位的加法,类比到十进制就是99+99=88;为啥呢?你想啊,二进制无非是0和1,那只有0和1相加是直接得1嘛,刚好就异或咯
    2. 两个数进行与操作,是每个位相加后产生的进位,类比到十进制就是99+99=11,就9+9=18嘛,进位为1,所以应该左移然后加上上面那个1
得到的不考虑 进位的结果就对了
    3. 进位+不考虑进位的结果  在十进制中,就是结果了,比如99+99 = 88+110 = 198,但二进制这里不是直接用异或就可以解决了,因为这个过程可能还有用进位
如:101+111,正确应该是=1100,不考虑进位的相加结果(异或)=010;  进位结果(与操作左移一个)=1010,你会发现1010+0010还有个进位,所以这里不能直接用异或解决,还要用一次上面的两步。
所以还是要用1,2步来做,直到进位为0
 
 
上下代码吧:
public class Solution {
    public int Add(int num1,int num2) {
        int push, sum;
        do {
            sum = num1 ^ num2;//不考虑进位的加法
            push = (num1 & num2) << 1;//每个位产生的进位,左移一个位才是应该进行加法的位置
            num1 = sum;
            num2 = push;
        } while(push != 0);
        
        return push ^ sum;
    }
}

3. 移位操作的简单应用 

①判断整数a是奇数还是偶数

  a&1 = 0 偶数

  a&1 = 1 奇数

这个原理也很容易理解嘛,在二进制中,除了第一位是1,其他都是偶数吧,8,4,2啥的,所以要是奇数,一定要第一位为1吧

②不用temp交换两个整数

先要直到一个原理——一个整数a在异或另一个整数b两次以后所得的值还是整数a。就6^2^2 =6,这个通过异或的特点也不难理解吧。

然后,要做到交换,只要分别进行

 a = a ^ b;  

 b = a ^ b; // b=a^b^b=a

 a = a ^ b; // a=a^b^a^b^b=a^b^a=b
原文地址:https://www.cnblogs.com/wangshen31/p/12304171.html