educoder 二进制数据的位运算_二进制与位运算实用操作汇总(基础篇)

位运算是最高效而且占用内存最少的算法操作,但也是最难看懂的操作。然而,关于位运算的用法,笔者查了许多资料,似乎都没有找到详细而系统的讲解资料。笔者对位运算的操作相当感兴趣,因此斗胆尝试对位运算来一个的总结。

本文先从基本概念出发,然后从基本概念推导出基础应用,然后再到算法题实战。层层推进,逐步迭代。

本人水平有限,如有勘误,敬请指正。

说明:本文会以Python的交互环境来做代码演示。关于本文的约定:非代码块中的二进制数以下标x来表示进制数,如十进制数15,用二进制表示为

,而用十六进制则表示为

所有代码块中的二进制数字都以0b开头,比如十进制数15,用二进制表示为0b1111;

有时候需要更直观地表示,会使用竖式表示,如两个二进制数的and操作表示为:

所有代码块中的十六进制数字都以0x开头,比如十进制数255,用十六进制表示为0xff;

bin()函数,是Python中把十进制转换为二进制的转换函数;

所有的位运算操作的命名均用英文命名,以增加辨识度。

概念篇

and 操作,操作符“&”

定义:称为按位与运算符。它对整型参数的每一个二进制位进行布尔与操作,即两个对应的二进制位同时为1时,才等于1。

or 操作,操作符“|”

定义:称为按位或运算符。它对整型参数的每一个二进制位进行布尔或操作,即两个对应的二进制位,任意一个为1时,就等于1。

xor操作,操作符“^”

定义:称为按位异或运算符。它对整型参数的每一个二进制位进行布尔异或操作,即两个对应的二进制位,有且仅有一个为1时,才等于1。

not操作,操作符“~”

定义:称为按位非运算符。它是一个单运算符,对运算数的所有二进制位进行取反操作。

shl操作,操作符“<

定义:称为按位左移运算符。它把第一个运算数的所有二进制位向左移动第二个运算数指定的位数,而新的二进制位补0。将一个数向左移动N个二进制位相当于将该数乘以2的N次方,比如:

shr操作,操作符“>>”

定义:称为按位右移运算符。它把第一个运算数的所有二进制位向右移动第二个运算数指定的位数。为了保持运算结果的符号不变,左边二进制位补 0 或 1 取决于原参数的符号位。如果第一个运算数是正的,运算结果最高位补 0;如果第一个运算数是负的,运算结果最高位补 1。将一个数向右移动N个二进制位相当于将该数除以2的N次方,比如:

(总是向负无穷方向取整)。

原理篇

进制转换

进制之间的转换其实是个数学问题,在实际应用中,我们基本上无需操心。因此这里想说的不是计算问题,而是逻辑问题。二进制与十六进制有着天然的联系——每四个二进制位可以代表一个十六进制位:

由上图可见,如果说二进制转十进制还要稍稍心算一下的话,那二进制转十六制可以马上得出。只要记住了一个十六进制位与四个二进制位的对应关系就好了。同理,八进制位与二进制的关系是,每三个二进制位对应一个八进制位,但实践中,八进制并不常见,因此点到即止。

那么,为什么二进制与十六进制在实践中更常见呢?这是与内存的储存单位有关。

字节与二进制数的关系

对于计算机而言,最小的储存单位是一个字节,英文为byte。byte既是一个单位,也是一种数据类型(关于数据类型的解释,可查阅C/C++、JAVA等静态类语言的相关资料,本文不作介绍)。对于一个byte的数据,用了八个二进制位去储存数据,因此能正好用两个十六进制位来省略表示(比十进制还少写一位)。这就是为什么在实际操作中,二进制与十六进制更常见的原因。

二进制运算符的操作范围

笔者查阅了许多二进制运算的相关资料,似乎都忽略了对这一点的介绍。二进制运算符的作用范围与参与运算的变量的数据类型有关,比如以JAVA为例:对于byte类型变量,由于byte以8-bit(8个二进制位)表示,因此相应的位运算符的作用范围就是8-bit;

对于int类型变量,由于int以32-bit表示,因此位运算符的作用范围就是32-bit;

假如两个大小不一的数据类型进行操作,那位运算的作用范围会以较大的数据类型作为基准范围。

二进制数的符号

有了数据类型的范围限定,因此才有了高位、低位、符号位的概念。高位,指在数据类型限定范围内靠左的二进制位;

低位,指在数据类型限定范围内靠右的二进制位;

符号位,指在数据类型限定范围内最左边的一个二进制位,符号位为0表示正数,1表示负数。(除了C语言存在无符号的值类型外,绝大部分语言的值类型都默认为有符号的数值类型)

因此,假如一个byte范围内的整数,提升为一个int范围内的整数,由于二进制位数的范围大了,必然需要进行补位,因此:当原byte整数为正数时,提升为int类型时,补位全部以0补位;

当原byte整数为负数时,提升为int类型时,补位全部以1补位;

为什么要这样做?因为这样才能保证数值在范围提升后,原值的十进制数不变。以下来看看JAVA的验证代码:

// byte类型的值范围是[-128,127]byte a = (byte) -55; //由于值在byte范围内,因此强制转换缩小变量内存范围不会改变原值byte b = (byte) 100;

System.out.println(Integer.toBinaryString(a)); //输出(二进制数):11111111111111111111111111001001System.out.println(Integer.valueOf(a)); //输出:-55(重新提升范围,值不变)System.out.println(Integer.toBinaryString(b)); //输出(二进制数):1100100(高位的0会被省略显示)System.out.println(Integer.valueOf(b)); //输出:100

二进制下的负数表示法

对于一个十进制的负数,我们经常把它看作是一个数加一个负号;然而对于二进制负数来讲,却不是一堆二进制位数加一个符号位。

二进制的正数与负数之间的关系更像是“进位”的关系。以下我们以一个byte值来举例:

如上所述,byte的数值范围是[-128,127]。

为了让表示更清楚,笔者特意把符号位隔开。留意从0到-1,由于非符号位全部为0,已经没有东西可减,但假如我们假设从更高的位借来了一个1,这样就能让

了;有了-1,那

就可以继续成立了……直到把除符号位之外的位全部减完,这时十进制数就相当于-128。因此,八位二进制数可以表达的数为

个,即[-128,127]。

二进制数的性质

由以上的二进制数变化规律,我们可以发现二进制数有以下性质:~x = -x - 1:从以上0与-1的按位关系可以看到,两者的二进制位正好取反;此规律能推广到1与-2,2与-3……等等。因此,该性质是not操作中最常使用的性质。

(~x)&x = 0:任意数与它的取反数的and操作结果为0。

(~x)|x = -1:任意数与它的取反数的or操作结果为-1。

(~x)^x = -1:任意数与它的取反数的xor操作结果为-1。

x|0 = x:任意数x与0的or操作结果为x自己。

x^0 = x:任意数x与0的xor操作结果为x自己。

x^y^y = x:任意数x与任意数y进行两次xor操作结果为x自己。

与四则运算一样,位运算也有它自己的定律。因此,我们有必要先熟悉并证明一下这些定律。

定律篇

and操作

交换律,a&b = b&a

证明:略(因为显然易见)

结合律,(a&b)&c = a&(b&c)

证明:只要证明一个二进制位,便能推广到N个二进制位。

(1&0)&0 = 1&(0&0) = 0;

1&1&0 = 1&(1&0) = 0。

or操作

交换律,a|b = b|a

证明:略

结合律,(a|b)|c = a|(b|c)

证明:只要证明一个二进制位,便能推广到N个二进制位。

(1|0)|0 = 1|(0|0) = 1;

1|1|0 = 1|(1|0) = 1。

xor操作

交换律,a^b = b^a

证明:略

结合律,(a^b)^c = a^(b^c)

证明:

not操作

结合律,a = ~(~a)

证明:略

shl操作

shr操作

继续深入传送门:黄伟亮:二进制与位运算实用操作汇总(应用篇)​zhuanlan.zhihu.com

参考资料:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537073.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业为什么要做SEO,它的重要性有哪些?

对于SEO工作而言&#xff0c;我们知道一个网站做SEO的基础诉求就是让用户和搜索引擎更好的理解网站内容&#xff0c;虽然随着搜索引擎算法技术的迭代&#xff0c;目前SEO面临更大的挑战与竞争&#xff0c;但基于搜索营销&#xff0c;它目前仍然显得十分重要。 那么&#xff0…

白话说编程之java线程

白话说编程之java线程线程和进程&#xff1a;进程&#xff1a;线程&#xff1a;线程和进程的区别&#xff1a;详解多线程:并发为什么使用并发并发的执行原理并行线程的五种状态&#xff1a;创建状态&#xff1a;就绪状态&#xff1a;运行状态&#xff1a;阻塞状态&#xff1a;死…

powerdesigner显示工具面板_photoshop教程-画笔工具预设与选项设置

定义画笔预设在打开的“画笔”面板中&#xff0c;单击左侧的“画笔笔尖形状”名称&#xff0c;可显示笔尖形状图案。单击“画笔”面板左侧其他不同的选项名称&#xff0c;在右侧就会显示其对应的调节项。只单击不同选项前面的方框&#xff0c;可使此选项有效&#xff0c;但右侧…

C#属性的声明和使用演示源码片段

工作闲暇时间&#xff0c;将代码过程重要的一些代码做个收藏&#xff0c;如下代码是关于C#属性的声明和使用演示片段的代码&#xff0c;应该对码农有一些好处。 using System; class Person {private string myName "N/A";private int myAge 0;public string Name{g…

深入理解== 和 equals 的区别

深入理解 和 equals 的本质区别简介区别&#xff1a;图解&#xff1a;注意点&#xff1a;源码分析&#xff1a;总结分享一波:程序员赚外快-必看的巅峰干货简介 初学者常常被" “和‘equals ’所折磨&#xff0c;为什么&#xff0c;因为他们的大概意思相同&#xff0c;都是…

rsem比对_RSEM方法比对和表达量计算

分析模块&#xff0c;封装了Trinity程序包中的“align_and_estimate_abundance.pl”脚本&#xff0c;进行原始数据与转录本序列的比对和表达量计算。其中&#xff0c;核心程序为&#xff0c;Bowtie或Bowtie2进行原始数据与转录本序列的比对&#xff0c;RSEM根据比对结果进行表达…

java sleep和wait区别

为什么80%的码农都做不了架构师&#xff1f;>>> 关于sleep和wait区别解析&#xff1a; sleep只是释放CPU资源&#xff0c;并不释放资源锁对象&#xff0c;wait是会释放掉资源锁对象。 比如&#xff0c;有个锁对象object&#xff0c;线程1和线程2都会锁住object对象…

u8转完看不到菜单_web网页有错误,无法看到操作菜单-用友U8

文章摘要&#xff1a;本文提供在用友U8V8.51erp软件财务会计管理的WEB财务模块中客户在使用WEB功能时&#xff0c;没有使用默认的设置&#xff0c;是将WEB功能设置在自己的网站上面&#xff0c;访问WEB功能没有问题&#xff0c;界面出来了&#xff0c;输入用户名、密码、选择帐…

.Net Core 项目引用本地类库方式(二)

上篇文章有详细的介绍.Net Core 项目中引用本地类库通过打包&#xff0c;然后Nugety引用方式&#xff0c;这里再介绍一种引用包的方式 转载于:https://www.cnblogs.com/wangshitou/p/10283800.html

深入理解equals和hashCode关系和区别

深入理解equals和hashCode关系和区别直入主题&#xff1a;区别&#xff1a;1.他们判断对象相同的方式不一样&#xff1a;2.他们判断对象是否相等的准确率不一样&#xff1a;改写equals时总是要改写hashcode分享一波:程序员赚外快-必看的巅峰干货为什么要说equals和hashCode这两…

lol韩服游戏内设置_韩服LOL进去了还不能玩?教你如何玩韩服!

领取免费韩服LOL安全号&#xff0c;百度搜索韩服LOL微博关注即可&#xff01;上图错误为常识性错误&#xff0c;LOL韩服游戏的安装文件路径有中文所导致的错误 解决方法&#xff1a;将安装路径里的中文改成英文即可 举例 包含中文汉字的文件夹都是错误的 Program FilesLOL韩服 …

Jdk 和 jre 的 关系和区别

Jdk 和 jre 的 关系和区别 区别&#xff1a; JDK&#xff1a;是Java Development Kit 的简称–>翻译过来就是&#xff1a;Java 开发工具包。是程序员使用java语言编写java程序所需的开发工具包&#xff0c;是提供给程序员使用的。 JRE&#xff1a;是Java Runtime Environm…

OpenCV-Python入门教程7-PyQt编写GUI界面

前面一直都是使用命令行运行代码&#xff0c;不够人性化。这篇用Python编写一个GUI界面&#xff0c;使用PyQt5编写图像处理程序。包括&#xff1a;打开、关闭摄像头&#xff0c;捕获图片&#xff0c;读取本地图片&#xff0c;灰度化和Otsu自动阈值分割的功能。 使用Qt Designer…

spark 广播变量大数据_大数据处理 | Spark集群搭建及基本使用

点击蓝字关注我前面用了一篇文章详细的介绍了集群HDFS文件系统的搭建&#xff0c;HDFS文件系统只是一个用于存储数据的系统&#xff0c;它主要是用来服务于大数据计算框架&#xff0c;例如MapReduce、Spark&#xff0c;本文就接着上一篇文章来详细介绍一下Spark集群的搭建及Spa…

如何将本地项目上传到gitee

*************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程 请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更…

oracle dg 备库未设置convert参数导致ORA-01111,ORA-01110

2019独角兽企业重金招聘Python工程师标准>>> 查看trace 文件&#xff1a; MRP0: Background Managed Standby Recovery process started (amls) started logmerger process Sun Jan 20 07:55:53 2019 Managed Standby Recovery starting Real Time Apply MRP0: Back…

git回退历史版本无法上传_Git系列教程(二):版本库中添加文件、版本回退

Git系列教程(一)&#xff1a;简介、安装、配置我们学习了分布式和版本控制系统的概念、Git具有的8个功能以及如何在Windows上安装Git、进行相关配置并创建版本库。Git版本库中添加文件Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。我们编写一个readme.txt文…

nginx反向代理配置如何去除前缀

使用nginx做反向代理的时候&#xff0c;可以简单的直接把请求原封不动的转发给下一个服务。设置proxy_pass请求只会替换域名&#xff0c;如果要根据不同的url后缀来访问不同的服务&#xff0c;则需要通过如下方法&#xff1a; 方法一&#xff1a;加"/"** server {l…

「作文素材详解」写作必知篇:语言优美不是作文第一要求

语言优美不是作文第一要求“教孩子写作文&#xff0c;老师家长应该先提升自己。”“语言优美不是作文的第一要求。”“如果教孩子写漂亮的违心话&#xff0c;会害了他一辈子。”日前&#xff0c;著名作家肖复兴来到体育东路小学&#xff0c;与广州的一线语文教师交流&#xff0…