常见位运算

简介: 常见位运算

前言
我们经常使用的加减乘除,我们所看到的只是表面的效果,那么加减乘除在底层究竟是怎么实现的?今天就让我们一探究竟.今天用位运算实现的加减乘除不使用任何的加减乘除符号.

一、常见位运算

  1. &运算

&运算二进制每一位全1为1,否则为0

public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a & b);
}

1
2
3
4
5

  1. |运算

|运算二进制每一位有1为1,全0为0

public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a | b);
}

1
2
3
4
5

  1. ^运算

^运算二进制每一位不同为1,相同为0

public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a ^ b);
}

1
2
3
4
5

  1. ~运算

~运算是二进制每一位按位取反.

public static void main(String[] args) {

    int a = 1;
    System.out.println(~a);
}

1
2
3
4

二、位运算实现加法
public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a + b);
}

1
2
3
4
5

下来我们用位运算实现一下加法.

我们进行一次异或运算就相当于进行一次无进位加法,那这样也不能实现加法,那我们得想办法,实现进位的数值.

进行一次与运算,只有同时为1才为1,也当同时为1时,我们需要进位,所以我们进行与运算后进行左移一位的操作,即可得到进位后的数值.

我们对异或运算和与运算后左移一位的结果进行相加即可,但我们只能进行位运算,所以我们只能再次进行异或运算与与运算,直到云运算的结果为0时,我们的异或运算的结果即为加法的结果.

public static int bitAdd(int a,int b) {

    int sum = 0;
    while(b != 0) {
        sum = a ^ b;
        b = (a & b) << 1;
        a = sum;
    }
    return sum;
}

public static void main(String[] args) {
    System.out.println(bitAdd(1,2));
}

1
2
3
4
5
6
7
8
9
10
11
12
13

三、位运算实现减法
public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a - b);
}

1
2
3
4
5

下来我们用位运算实现一下减法.
在我们有了位运算实现加法的基础之后,我们的减法就变得简单了,a - b == a + ( -b ),所以我们只需要将b变为-b即可实现减法功能,但我们不能使用负号,那我们来用位运算来实现一下.

public static void main(String[] args) {

    System.out.println(~3);
}

1
2
3

我们可以发现一个数取反与相反数差一,我们取反加一即可得到相反数.

public static void main(String[] args) {

    System.out.println(~3 + 1);
}

1
2
3

public static int bitAdd(int a,int b) {

    int sum = 0;
    while(b != 0) {
        sum = a ^ b;
        b = (a & b) << 1;
        a = sum;
    }
    return sum;
}

public static int bitSub(int a,int b) {
    return bitAdd(a,~b+1);
}

public static void main(String[] args) {
    System.out.println(bitSub(1,3));
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

四、位运算实现乘法
public static void main(String[] args) {

    int a = 1;
    int b = 3;
    System.out.println(a * b);
}

1
2
3
4
5

我们小学的时候是怎么进行乘法的,按位相乘,每一位和每一位相乘.

二进制中也是一样的,按位相乘,如果被乘数二进制位是1则与乘数相乘.每次运算进行移位

public static int bitAdd(int a,int b) {

    int sum = 0;
    while(b != 0) {
        sum = a ^ b;
        b = (a & b) << 1;
        a = sum;
    }
    return sum;
}
public static int bitMul(int a,int b) {
    int sum = 0;
    while(b != 0) {
        if((b & 1) != 0) {
            sum += a;
        }
        a <<= 1;
        b >>>= 1;
    }
    return sum;
}

public static void main(String[] args) {
    System.out.println(bitMul(1,3));
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

四、位运算实现除法
public static void main(String[] args) {

    int a = 7;
    int b = 2;
    System.out.println(a / b);
}

1
2
3
4
5

我们在用位运算实现除法时,采用逆推的方式,a / b = c,
a = c * b。

我们只需要求出a减去b向左的移位,只要满足a <= b的移位即可,每次移动多少位即a / b的结果二进制中某一位为1,以此循环倒推即可.

public static int bitAdd(int a,int b) {

    int sum = 0;
    while(b != 0) {
        sum = a ^ b;
        b = (a & b) << 1;
        a = sum;
    }
    return sum;
}
public static int negNum(int n) {
    //转化为相反数
    return bitAdd(~n,1);
}
public static int minus(int a,int b) {
    //实现两个数相减
    return bitAdd(a,negNum(b));
}
public static boolean isNeg(int n) {
    //判断是否为负数
    return n < 0;
}
public static int bitDiv(int a,int b) {
    int x = isNeg(a) ? negNum(a) : a;
    int y = isNeg(b) ? negNum(b) : b;
    int res = 0;
    for (int i = 30; i >= 0 ; i = minus(i,1)) {
        if((x >> i) >= y) {
            res |= (1 << i);
            x = minus(x,y << i);
        }
    }
    return isNeg(a) != isNeg(b) ? negNum(res) : res;

}

public static void main(String[] args) {
    int a = 7;
    int b = 2;
    System.out.println(bitDiv(a,b));
}

相关文章
|
C++ 索引 容器
c++string容器-子串获取讲解
c++string容器-子串获取讲解
752 0
|
存储 Kubernetes NoSQL
无锁队列实现及使用场景
无锁队列实现及使用场景
基于VisualGLM-6B大模型的本地部署与推理
本文是基于清华开源的VisualGLM-6B 支持图像中英文的多模态对话语言模型,进行了一系列本地的简单部署,包括环境配置、模型部署、演示推理、模型微调(官方提供的代码),由于个人电脑显存不足,最后是在阿里云服务器交互式平台DSW终端进行微调和训练操作的。
388 17
|
9月前
|
存储 人工智能 编解码
Deepseek 3FS解读与源码分析(2):网络通信模块分析
2025年2月28日,DeepSeek 正式开源其颠覆性文件系统Fire-Flyer 3FS(以下简称3FS),重新定义了分布式存储的性能边界。本文基于DeepSeek发表的技术报告与开源代码,深度解析 3FS 网络通信模块的核心设计及其对AI基础设施的革新意义。
Deepseek 3FS解读与源码分析(2):网络通信模块分析
|
9月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
448 0
|
监控 前端开发 API
实战指南:使用Python Flask与WebSocket实现高效的前后端分离实时系统
【7月更文挑战第18天】构建实时Web应用,如聊天室,可借助Python的Flask和WebSocket。安装Flask及Flask-SocketIO库,创建Flask应用,处理WebSocket事件。前端模板通过Socket.IO库连接服务器,发送和接收消息。运行应用,实现实时通信。此示例展现了Flask结合WebSocket实现前后端实时交互的能力。
1484 3
|
编解码 人工智能 自然语言处理
|
存储 NoSQL MongoDB
MongoDB 创建集合
10月更文挑战第13天
241 1
|
数据可视化 Python
Python中的数据可视化:使用Matplotlib绘制图表
【9月更文挑战第11天】在这篇文章中,我们将探索如何使用Python的Matplotlib库来创建各种数据可视化。我们将从基本的折线图开始,然后逐步介绍如何添加更多的功能和样式,以使您的图表更具吸引力和信息量。无论您是数据科学家、分析师还是任何需要将数据转化为视觉形式的专业人士,这篇文章都将为您提供一个坚实的起点。让我们一起潜入数据的海洋,用视觉的力量揭示其背后的故事。
239 17
|
Kubernetes Docker 容器
容器运行时Containerd k8s
容器运行时Containerd k8s
197 3