当前位置: 首页 > article >正文

位运算算法篇:进入位运算的世界

位运算算法篇:进入位运算的世界

本篇文章是我们位运算算法篇的第一章,那么在我们是算法世界中,有那么多重要以及有趣的算法,比如深度优先搜索算法以及BFS以及动态规划算法等等,那么我们位运算在这些算法面前相比,位运算就显得十分的低调,但是它仍然是一个十分重要的算法,所以我将用三到四篇文章来介绍我们的位运算,帮你领略我们位运算的神奇与各种骚操作,那么废话不多说,我们进入我们位运算的学习

1.二进制

那么在了解我们各种位运算之前,我们得先知道我们为什么要学习我们的位运算,对于我们的计算机来说,我们计算机的底层硬件只能识别由0和1组成的二进制语言,那么意味着任何数据在底层都是以二进制的形式存储的,其中就包括我们的各种数据类型比如我们的整形以及字符类型等等,那么既然这些数据统一都是以二进制形式存取,那么我们的位运算就是以二进制序列为基础展开的运算,所以可想而知位运算的重要性。


那么我们刚才也说了,各种的整形底层也都是以二进制的形式存在,那么对于我们的整形来说,我们可以将一个整形分为无符号整形以及有符号整形,那么所谓无符号整形我们很好理解,那么该整形的二进制位全部都用来作为数值位,那么也就意味着我们的无符号整形只有非负数,那么以32位的int类型为例,那么它的32个二进制位都可以作数值位,那么每一个二进制位要么是0要么是1,那么也就意味着我们的int类型的范围是0到2的32次方减一。

而对于有符号整形,我们知道在我们现实生活中,我们用正负号来区分我们的数的正负,而在我们计算机世界中,我们的数据只有0和1组成,任何数据都只能表示为0与1组成的二进制序列,那么要表达正负数,我们将一个数的最高位设置为符号位,其中0表示为正数,那么1表示为负数,其余则是作为数值位

那么对于正数来说,除了最最高位为0,其余都是数值位,那么我们按照每个数值位所对应的权值来得到一个十进制数,但是对于负数,我们采取了一个特殊的设计

那么我们的整形分为了原码以及反码和补码,那么我们计算机中存取的都是补码,那么我们正数的原码以及反码和补码都是一样的,而对于我们的负数来说,我们得到一个负数的补码,那么首先我们得将负数的补码除最改为符号位其余按位取反,然后再加1就得到我们的负数的原码,那么我们该原码的数值位就是我们该负数的绝对值,那么我们得到负数的绝对值,前面加一个符号即可。所以我们看到一个整形的二进制序列,先看符号位,如果是0,代表正数,1则是负数,然后将其转换为原码来解读出它对应的10进制数

假设以4个比特位为例: 1110

1.最高位是1,那么负数

2.按位取反(~) 1001

3.取反后再加1 1010

4.解读数值位 得到 -2

那么相信通过我刚才的介绍你一定能够熟练的掌握有符号整形的识别与转化,那么想必你一定有一个疑问,那么也就是我们对于负数为什么要这么设计呢?

那么我们知道我们的CPU的计算机只有我们的加法器,那么我们关于我们整形的乘法以及出发运算都要通过我们的加法运算来实现,那么对于加法运算来说,我们的正数加正数那么就正常的按照我们二进制的计算规则逢2进1计算即可,但是对于正数加负数,那么我们知道我们正数加负数,我们现实世界中计算,那么我们首先得判断两个数的绝对值,然后让绝对值大的减去绝对值小的,那么我们要做到,必然就要涉及到条件判断,那么条件判断肯定会影响效率,所以能不能采取统一的规则,不关心该数是正还是负,都能用统一的方式来计算,那么这就是补码出现的意义:

那么它做到了让我们计算一个二进制序列不要关心正负,按照正数加正数的那套逻辑得到值,如果是负数的话,我们按照上文所说的,将其转换为原码就能得到该数的具体数值是什么了,你下来可以动手实践一下,结果肯定都是一定满足的。

比如5+(-3)假设以4个比特位为例

那么5的二进制序列0101

​ 3的补码:1101

​ 计算过程 0101

​ 1101

​ -----------

​ 0010

那么0010对应的10进制数就是我们的2

2.位运算

那么刚才引入了二进制的相关知识,那么我们再来介绍我们几个常见的位运算,

那么我们的位运算可以分为两大类,分别是算术运算以及逻辑运算,那么我们首先先讲解一下我们的算术运算:

或运算(|):

那么我们的或运算的运算规则则是对应的二进制位只要为1,那么结果一定为1,如果对应的二进制位全部是0,那么计算的结果才是0,或运算同时可以引入到逻辑运算中,只有运算的条件全部为false,结果才为false

0 | 0 =0

1| 0=1

1 | 1=1

与运算(&):

与运算的规则则是我们对应的二进制位全部为1结果才为1,其余则全是0,对应逻辑运算则是条件全为真,结果才为真。

1 & 1=1

1& 0 =0

异或运算(^):

异或运算的规则则是相同为0,相异为1

1^0 =1

1^ 1=0

0^ 0=0

右移运算符:

那么我们的右移运算符则分为两种分别是算术右移以及逻辑右移

那么逻辑右移(>>>)则是我们将我们的二进制序列整体往右移动,然后左边补0,但是我们知道对于有符号整形来说,它的最高位为符号位,那么如果采取这种右移方式,那么它的正负会颠倒,对数值会改变,所以我们有第二种方式

算术右移(>>),那么它则是左边不是补0,而是补充符号位,那么对于负数来说,那么它则是会在左边依次补1。

并且我们要注意我们的右移运算符,那么它只是一个动作,也就是说我们对一个整形的变量左移了n位,那么右移后的结果会保存在一个临时变量中,而不是对原变量直接进行右移,同理对于左移,那么我们可以简单的用代码来验证:

#include <stdio.h>int main() {int original = 8; // 二进制:00001000int leftShifted = original << 2; // 左移两位,二进制:00010000,即16int rightShifted = original >> 2; // 右移两位,二进制:00000010,即2printf("Original: %d\n", original);printf("Left Shifted: %d\n", leftShifted);printf("Right Shifted: %d\n", rightShifted);return 0;
}

在这里插入图片描述

左移运算符(<<):

那么我们的左移运算符就不用像刚才的那样分为逻辑以及算术,那么我们的左移运算符的右边统一用0来补充。

那么对于逻辑右移运算符以及左移运算,我们每次逻辑左移动一位就相当于在原数的基础上除了2,每次右移动一位就相当于在原数的基础上乘以了2


逻辑运算:

逻辑或运算符(||):

那么我们的逻辑或运算符的运算规则和或运算符一致,只有有一个条件为真,结果为真,但是注意的是,我们逻辑或运算符没有穿透性,也就是说我们逻辑或运算符是从左往右依次进行条件判断,一旦判断到有一个条件表达式为真,那么它就不在执行之后的条件判断,直接返回结果为真,而我们的或运算则是要依次从左到右判断完

那么我们可以写一个代码来验证:

#include<iostream>
using namespace std;
bool returntrue(void)
{cout<<"run this succcessfully ";return true;
}
bool returnfalse(void)
{cout<<"run this successfully";return false;
}
int main()
{cout<<"Test1:"<<endl;bool res=returntrue()||returnfalse();cout<<endl;cout<<"Test2:"<<endl;res=returntrue()|returnfalse();return 0;
}

在这里插入图片描述

逻辑与运算符(&&):

运算规则也是和与&运算一致,但是注意我们的逻辑与运算也不具有穿透性,它也是从左往右依次判断条件表达式的真值,一旦我们的中间的某个条件表达式为假,那么它就不再往后执行后面的条件判断语句,直接返回false

同样也是与上面一套的代码逻辑稍加修改来验证:

#include<iostream>
using namespace std;
bool returntrue(void)
{cout<<"run this succcessfully ";return true;
}
bool returnfalse(void)
{cout<<"run this successfully";return false;
}
int main()
{cout<<"Test1:"<<endl;bool res=returnfalse()&&returntrue();cout<<endl;cout<<"Test2:"<<endl;res=returntrue()|returnfalse();return 0;
}

在这里插入图片描述

3.实践

那么我们有了上述的知识,那么我们可以根据我们本篇文章所讲的全部内容来自己实现一个打印一个数的二进制序列。

那么具体实现的原理也很简单,那么就是我们的利用我们的位运算,我们对于一个int类型的数,那么它有32个二进制位,那么我们打印它所有的32个二进制位,我们就得从左往右依次打印每一个二进制位,那么我们利用我们的与运算,那么与运算的规则是对应的二进制位只要有1,那么结果为1,全部为0,结果则为0,那么我们知道我们十进制的1,那么对应的二进制序列就是只有最低位的二级制位为1,其余为0,那么我们将他依次左移到最高位,然后进行与运算,然后判断是否为0然后依次打印判断后的结果即可,那么如下则是我们的代码实现:

#include<iostream>
using namespace std;
void Print(int a)
{for(int i=31;i>=0;i--){int ant=(1<<i)&a;if(ant==0){cout<<0;}else{cout<<1;} 	}cout<<endl;
}
int main()
{int a=80;Print(a);return 0;
}

在这里插入图片描述

**注意我们如果要打印一个long类型的数,那么我们首先得将我们的1移到最高位也就是第63位,但是我们编译器默认我们的1是int类型,所以直接移动会溢出,所以我们得将我们的1设置为long类型,在进行左移

4.结语

那么本文介绍了我们的位运算的前置知识,比如整形的原反补码,和相应的位运算,那么我们在根据今天所讲的内容自己实现了一个打印一个数的二进制序列,那么下一篇文章我会详解我们的异或运算的一些骚操作,那么我们会持续更新,希望你能够多多关照与支持,希望本篇文章能够让你有所收获!
在这里插入图片描述

相关文章:

位运算算法篇:进入位运算的世界

位运算算法篇&#xff1a;进入位运算的世界 本篇文章是我们位运算算法篇的第一章&#xff0c;那么在我们是算法世界中&#xff0c;有那么多重要以及有趣的算法&#xff0c;比如深度优先搜索算法以及BFS以及动态规划算法等等&#xff0c;那么我们位运算在这些算法面前相比&#…...

.net一些知识点5

1.dot Net带out的参数如何使用 string name;//假设这个参数带out TestMethod(1,out name);//一定要有out 方法体中&#xff0c;一定要有out参数的赋值&#xff0c;并且能输出 2.参数的传递方式有哪些 a.值传递 b.引用传递 ref c.输出传递 out 3.设计模式知道哪些 3.us…...

高端入门:Ollama 本地高效部署DeepSeek模型深度搜索解决方案

目录 一、Ollama 介绍 二、Ollama下载 2.1 官网下载 2.2 GitHub下载 三、模型库 四、Ollmal 使用 4.1 模型运行&#xff08;下载&#xff09; 4.2 模型提问 五、Ollama 常用命令 相关推荐 一、Ollama 介绍 Ollama是一个专为在本地机器上便捷部署和运行大型语言模型&…...

Cursor无法使用老版本python debug的解决办法

我服务器上的python版本是3.6.8&#xff0c;使用官方的python插件进行debug的时候&#xff0c;弹窗提示说不支持3.7以下的&#xff0c;建议升级python&#xff0c;但是我的工程就是3.6.8的屎山&#xff0c;辗转发现一个土办法&#xff1a; 手动下载老版本的python插件&#xff…...

webpack配置之---output.filename

output.filename 在 Webpack 中&#xff0c;output.filename 配置项用来指定打包后生成的文件名称。它是 Webpack 构建输出目录中的关键部分&#xff0c;决定了生成文件的名字格式。 1. 基本字符串配置 最简单的配置方式是通过字符串设置文件名。比如&#xff1a; module.e…...

如今物联网的快速发展对hmi的更新有哪些积极影响

一、功能更加丰富 物联网的快速发展使得 HMI&#xff08;人机界面&#xff09;能够连接更多的设备和系统&#xff0c;从而实现更加丰富的功能。例如&#xff0c;通过与传感器网络的连接&#xff0c;HMI 可以实时显示设备的运行状态、环境参数等信息&#xff0c;为用户提供更加…...

黑马 Linux零基础快速入门到精通 笔记

初识Linux Linux简介 提及操作系统&#xff0c;我们可能最先想到的是windows和mac&#xff0c;这两者都属于个人桌面操作系统领域&#xff0c;而Linux则属于服务器操作系统领域。无论是后端软件、大数据系统、网页服务等等都需要运行在Linux操作系统上。 Linux是一个开源的操作…...

Go 中的 7 个常见接口错误

Go 仍然是一门新语言,如果你正在使用它,它很可能不是你的第一门编程语言。 不同的语言,既为你带来了经验,也带来了偏见。你用以前的任何语言做的事情,在 Go 中用相同的方法可能不是一个好主意。 学习 Go 不仅仅是学习一种新的语法。这也是学习一种新的思维方式来思考你的…...

LLAMA-Factory安装教程(解决报错cannot allocate memory in static TLS block的问题)

步骤一&#xff1a; 下载基础镜像 # 配置docker DNS vi /etc/docker/daemon.json # daemon.json文件中 { "insecure-registries": ["https://swr.cn-east-317.qdrgznjszx.com"], "registry-mirrors": ["https://docker.mirrors.ustc.edu.c…...

二级C语言题解:十进制转其他进制、非素数求和、重复数统计

目录 一、程序填空&#x1f4dd; --- 十进制转其他进制 题目&#x1f4c3; 分析&#x1f9d0; 二、程序修改&#x1f6e0;️ --- 非素数求和 题目&#x1f4c3; 分析&#x1f9d0; 三、程序设计&#x1f4bb; --- 重复数统计 题目&#x1f4c3; 分析&#x1f9d0; 前言…...

Unity3D引擎首次用于光伏仿真设计软件爆火

在光伏设计领域&#xff0c;绿虫光伏仿真设计软件宛如一匹黑马&#xff0c;凭借其基于 Unity3D 引擎的强大功能&#xff0c;为行业带来了全新的解决方案。借助 Unity3D 引擎技术&#xff0c;实现了游戏级高清画面&#xff0c;2D/3D 自由转换&#xff0c;让场景代入感极强&#…...

基础入门-网站协议身份鉴权OAuth2安全Token令牌JWT值Authirization标头

知识点&#xff1a; 1、网站协议-http/https安全差异&#xff08;抓包&#xff09; 2、身份鉴权-HTTP头&OAuth2&JWT&Token 一、演示案例-网站协议-http&https-安全测试差异性 1、加密方式 HTTP&#xff1a;使用明文传输&#xff0c;数据在传输过程中可以被…...

深入理解 C++17 std::is_swappable

文章目录 深入理解 C17 std::is_swappable引言std::is_swappable 概述std::is_swappable 的工作原理std::is_swappable 的变体注意事项结论 深入理解 C17 std::is_swappable 引言 在 C 编程中&#xff0c;交换两个对象的值是一个常见的操作。为了确保代码的通用性和安全性&am…...

Oracle常用响应文件介绍(19c)

文章目录 1. 数据库安装响应文件1.1 响应文件模板1.2 参数说明1.2.1 响应文件版本参数1.2.2 安装选项参数1.2.3 Unix 用户组参数1.2.4 软件清单参数1.2.5 安装目录参数1.2.6 安装版本参数1.2.7 特权操作权限组指定参数1.2.8 Root脚本执行配置参数1.2.9 Grid选项配置参数1.2.10 …...

Vue(4)

一.组件的三大组成部分-注意点说明 &#xff08;1&#xff09;scoped样式冲突 默认情况&#xff1a;写在组件中的样式会全局生效 → 因此很容易造成多个组件之间的样式冲突 ①全局样式&#xff1a;默认组件中的样式会作用到全局 ②局部样式&#xff1a;可以给组件加上scoped属…...

4G核心网的演变与创新:从传统到虚拟化的跨越

4G核心网 随着移动通信技术的不断发展&#xff0c;4G核心网已经经历了从传统的硬件密集型架构到现代化、虚拟化网络架构的重大转型。这一演变不仅提升了网络的灵活性和可扩展性&#xff0c;也为未来的5G、物联网&#xff08;LOT&#xff09;和边缘计算等技术的发展奠定了基础。…...

探讨如何在AS上构建webrtc(2)从sdk/android/Build.gn开始

全文七千多字&#xff0c;示例代码居多别担心&#xff0c;没有废话&#xff0c;不建议跳读。 零、梦开始的地方 要发美梦得先入睡&#xff0c;要入睡得找能躺平的地方。那么能躺平编译webrtc-android的地方在哪&#xff1f;在./src/sdk/android/Build.gn。Build.gn是Build.nin…...

C语言时间相关宏定义

在C语言中&#xff0c;预处理器提供了一些与时间相关的宏定义&#xff0c;用于在编译时获取日期、时间等信息。除了 __TIMESTAMP__ 和 __DATE__&#xff0c;还有以下相关的宏定义&#xff1a; __DATE__ 当前编译日期的字符串&#xff0c;格式为 "Mmm dd yyyy"&#x…...

【Linux基础】Linux下常用的系统命令

一、前言 本文主要总结了工作中常用的linux指令&#xff0c;有遇到新的命令会不定期更新。 二、系统监控和进程管理指令 2.1 ps命令 作用&#xff1a;查看当前进程信息。 常用选项&#xff1a; -e: 显示所有进程&#xff0c;包括其他用户的进程。-f: 显示更详细的进程信息…...

Spring Boot 线程池自定义拒绝策略:解决任务堆积与丢失问题

如何通过自定义线程池提升系统稳定性 背景 在高并发系统中&#xff0c;线程池管理至关重要。默认线程池可能导致&#xff1a; 资源浪费&#xff08;创建过多线程导致 OOM&#xff09;任务堆积&#xff08;队列满后任务被拒绝&#xff09;任务丢失&#xff08;默认拒绝策略丢…...

人工智能D* Lite 算法-动态障碍物处理、多步预测和启发式函数优化

在智能驾驶领域&#xff0c;D* Lite 算法是一种高效的动态路径规划算法&#xff0c;适用于处理环境变化时的路径重规划问题。以下将为你展示 D* Lite 算法的高级用法&#xff0c;包含动态障碍物处理、多步预测和启发式函数优化等方面的代码实现。 代码实现 import heapq impo…...

C#常用集合优缺点对比

先上结论&#xff1a; 在C#中&#xff0c;链表、一维数组、字典、List<T>和ArrayList是常见的数据集合类型&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。以下是它们的比较&#xff1a; 1. 一维数组 (T[]) 优点&#xff1a; 性能高&#xff1a;数组在内存中…...

多线程下jdk1.7的头插法导致的死循环问题

20250208 多线程下jdk1.7的头插法导致的死循环问题 多线程下jdk1.7的头插法导致的死循环问题 【新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频面试真题&#xff09;】 jdk1.7在hashmap扩容时使用的是头插法&#xff0c;所以扩容…...

MySQL的深度分页如何优化?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL的深度分页如何优化?】面试题。希望对大家有帮助&#xff1b; MySQL的深度分页如何优化? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MySQL在处理深度分页&#xff08;即查询页数较大时&#xff0c;通常是查询…...

uniapp中使用uCharts折线图X轴数据间隔显示

1、先看官网 https://www.ucharts.cn/ 2、设置代码 "xAxisDemo3":function(val, index, opts){if(index % 2 0){return val}else {return }}, 再在数据中引入设置好样式...

VMware下Linux和macOS安装VSCode一些总结

本文介绍VMware下Linux和macOS安装VSCode的一些内容&#xff0c;包括VSCode编译器显示中文以及安装.NET环境和Python环境。 VSCode下载地址&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 一.Linux系统下 1.安装中文包 按 Ctrl Shift P 打开命令面板。输…...

公司配置内网穿透方法笔记

一、目的 公司内部有局域网&#xff0c;局域网上有ftp服务器&#xff0c;有windows桌面服务器&#xff1b; 在内网环境下&#xff0c;是可以访问ftp服务器以及用远程桌面登录windows桌面服务器的&#xff1b; 现在想居家办公时&#xff0c;也能访问到公司内网的ftp服务器和win…...

【Windows/C++/yolo开发部署02:正确方法】将自定义实例分割模型导出为 ONNX 格式

【完整项目下载地址】: 【TensorRT部署YOLO项目:实例分割+目标检测】+【C++和python两种方式】+【支持linux和windows】资源-CSDN文库 目录 写在前面 环境准备 安装必要的库 下载模型并开始转换 解决依赖问题 安装 ONNX 降级 Protobuf 最终转换 总结 写在前面 在…...

国产编辑器EverEdit - 编辑辅助功能介绍

1 编辑辅助功能 1.1 各编辑辅助选项说明 1.1.1 行号 打开该选项时&#xff0c;在编辑器主窗口左侧显示行号&#xff0c;如下图所示&#xff1a; 1.1.2 文档地图 打开该选项时&#xff0c;在编辑器主窗口右侧靠近垂直滚动条的地方显示代码的缩略图&#xff0c;如下图所示&…...

Jupyter Notebook自动保存失败等问题的解决

一、未生成配置文件 需要在命令行中&#xff0c;执行下面的命令自动生成配置文件 jupyter notebook --generate-config 执行后会在 C:\Users\用户名\.jupyter目录中生成文件 jupyter_notebook_config.py 二、在网页端打开Jupyter Notebook后文件保存失败&#xff1b;运行代码…...