Java中的位运算

位运算

1、基础知识

  • 计算机中存储的都是补码

  • 正数的补码是他本身,负数的补码为反码加1(这里值我们看到的实际的负数,在计算机中其实本身就是存的补码)

  • ~按位取反,^异或,&与,|

    • 按位取反计算公式:~x = -x - 1
    • 注意,按位取反和反码的区别,正数也可以按位取反,但是正数的反码是他本身
      • 5 = 0000 0000 0000 0000 0000 0000 0000 0101
      • 5的反码 = 0000 0000 0000 0000 0000 0000 0000 0101
      • ~5 = 1111 1111 1111 1111 1111 1111 1111 1010
        • 将其视为某个数的补码,-1为反码:1111 1111 1111 1111 1111 1111 1111 1001
        • 取反得到源码: 1000 0000 0000 0000 0000 0000 0000 0110 = -6 (符号位不变)
        • 相当于套公式:~5 = -5 - 1
  • <<左移(乘以2), >>有符号右移(除2,左边补符号), >>>无符号右移(除2,左边补0)

  • 加减乘除

    • 加法:先通过异或不带进位的加,在通过与的方式添加进位(JZ65 不用加减乘除做加法

      • // x + y
        while(y>0){ // 是否有进位
            int tem = x ^ y; // 不进位的加
            y = (x & y) << 1; // y保存进位并左移一位
            x = tem; // x保存本次结果
        }
        
    • 减法:将被减数变为负数(被减数变为其相反数,即需要计算机存这个数相反数的补码,按位取反加一)

      • // x - y
        y = (~y) + 1;
        add(x,y);
        
    • 乘法:先转为正数,通过多次加法实现乘法的效果,再通过是否同号决定符号

    • 除法:同上,不停的减去被减数,直到减数小于被减数,记录次数

2、模板

(1)位的加法模板
public int add(int x,int y){
   // x + y
    while(y>0){ // 是否有进位
        int tem = x ^ y; // 不进位的加
        y = (x & y) << 1; // y保存进位并左移一位
        x = tem; // x保存本次结果
    }
    return x;
}
(2)快速乘模板
  • 理解

    x * y 举例

    2 * 11 = 2 * ( 1011 ) // 转为二进制

    2 * 11 = 2 * 1 * 2^0 + 2 * 1 * 2^1 + 2 * 1 * 2^3 = 2 + 4 + 16 = 22

  • 所以转变过程为:每次x都乘以2,当y的对应位置为1时,结果ans+=x

// 快速乘
public long quickAdd(long x,long k) {
     long ans = 0;
     while(k>0){
         if((k & 1) == 1){ // 判断这个位置上是不是1
             ans += x; // 为1就加x
         }
         k>>=1; // k就带符号右移,相当于除以2
         x += x; // x *= 2
     }
     return ans;
 }

3、例题(牛客网剑指offer)

位运算
(1)JZ15 二进制中1的个数
(2)JZ65 不用加减乘除做加法
快速乘
(1)leetcode 29. 两数相除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值