重学Android:从位运算到二进制表示(零)

前言

以下内容针对非科班同学,可以快速掌握位运算和二进制表示等计算机基础运算知识,看过源码的同学都知道,源码中大量运用了位运算知识,如果你对这方面不了解的话,看起来是比较困难的,如果你工作接触到蓝牙数据,串口数据收发等内容,这方面更是你必须了解的。

首先说下我自己,以前非科班出身,这方面内容几乎没了解过,但从实习开始领导直接告诉我让我负责蓝牙(用485通信的运动数据蓝牙模块)传输这方面工作(回头想想工作这几年一共接触到了不下于8种不同的蓝牙模块协议),就开始疯狂恶补这方面内容16进制,位运算,异或校验,校验和,进制转换......,越看越蒙,发现短期内并不能完全理解,于是就边学边开发,不知不觉就突然懂了,就是这么神奇,所以说如果前期看不懂没关系,看到能认识就行,再翻翻笔记理解一下,慢慢就懂了(经验之谈)!

说的有点多,直接开搂!

1. 二进制表达形式

1.1 什么是二进制?

计算机内部是通过二进制(0和1)来存储和处理数据的。每一位(bit)只能取两个值,0或1,而多个二进制位(bit)组合起来可以表示不同的数值。比如,8个二进制位可以表示的数值范围是0000000011111111,即0到255,也代表一个字节。

1.1 高位低位?

我们或许在某些地方听说过,高几位和低几位之说,它们都是对于二进制而言诞生的,比如一个字节 8个bit 00010010 通常把左边的称为高位,右边的称为低位,可以叫高四位0001和低四位0010,这没什么讲的,大家了解就行。

2. 位运算概述

位运算是直接对二进制位进行操作的运算方式,常用于底层开发、性能优化和算法实现中。与普通的算数运算(加法、减法等)不同,位运算操作的是二进制位,速度极快,且适用于很多底层系统和嵌入式开发。常见的位运算包括:位与(&)、位或(|)、位异或(^)、位取非(~)、左移(<<)、右移(>>)以及无符号右移(>>>)。

2.1 位与(&)

位与(&)是一个二元运算符,它对比特位上的两个数字进行操作。当且仅当两个相应的位都是1时,结果才为1,否则为0。

举个栗子:

scss 复制代码
  1101 (13)  
& 1011 (11)  
----------
  1001 (9)

只有第二位和第四位都为1,所以结果是1001,即9。通常使用(&)提取相应位的值,比如获取一个字节的高4位 就 &0xF0,获取低四位就 &0x0F

2.2 位或(|)

位或(|)也是一个二元运算符,它会将两个数字的对应位进行比较,只要其中一个位为1,结果就是1。

举个栗子:

scss 复制代码
  1101 (13)  
| 1011 (11)  
----------
  1111 (15)

只有第二位和第四位都为0时才是0,其它位只要有一个为1,结果就为1。所以结果是1111,即15。这个通常运用是将高位和低位相加得到一个值,比如一个值使用高四位存储数值另一个用低四位存储,那么使用(|)就能等到他俩的累加和。

2.3 位异或(^)

位异或(^)是一个二元运算符,两个位相同则结果为0,不同则结果为1。

举个栗子:

scss 复制代码
  1101 (13)  
^ 1011 (11)  
----------
  0110 (6)

这个的应用一般是计算数据帧的校验(异或校验),确保帧完整。

2.4 位取非(~)

位取非(~)是一个一元运算符,它对每一位进行反转操作,将0变成1,将1变成0。

举个栗子:

scss 复制代码
  ~1101 (13)
  ---------
   0010 (-14)  (假设使用4位表示,反转操作会影响符号位)

位取非对一个数的二进制表示进行反转。在计算机中,取非的结果通常会被解释为负数,因为它的符号位(最高位)发生了变化。

2.5 左移(<<)

左移运算符(<<)是将数字的二进制表示向左移动若干位,左移相当于将数值乘以2的幂。左移时,低位补0。

举个栗子:

scss 复制代码
  00000001 (1)  
<< 2   
-----------
  00000100 (4)

1左移两位后变成了4。每左移一位,相当于将数字乘以2。位运算由于是直接操作位,所以运算极快,现在知道为啥源码中这么常见了吧。

2.6 右移(>>)

右移运算符(>>)是将数字的二进制表示向右移动若干位,右移相当于将数值除以2的幂。右移时,符号位会根据符号来进行扩展。

举个栗子:

scss 复制代码
  11100101 (-27)  
>> 3  
-----------
  11111100 (-4)

-27右移3位后变成了-4。右移时,高位补充符号位(在负数情况下为1)。这时候肯定会有人疑惑包括我在内,就算保留符号位,右移三位也是10001100啊,为什么是11111100,这里就简单记住负数移位后的空缺位将用1填充,正数是0填充,这是因为负数一般用补码表示,马上会介绍。

这里只是个特殊的栗子讲解下,开发中最常用的是正数的右移,对于负数我几乎没碰到过。

2.7 无符号右移(>>>)

无符号右移(>>>)与带符号的右移不同,它不保留符号位,而是补充0到高位。

举个栗子:

scss 复制代码
  11100101 (-27)  
>>> 3   
-----------
  00011100 (28)

-27无符号右移3位后变成了28,因为无符号右移会用0补充符号位。

小结

运算符 符号 描述 示例 结果解释
位与 & 如果对应位都是1,则结果为1;否则为0。 1101 & 1011 1001(13 & 11 = 9)
位或 如果对应位中至少有一个1,则结果为1;否则为0。 1101 丨1011 1111(13 | 11 = 15)
位异或 ^ 如果对应位不同,则结果为1;如果相同,则为0。 1101 ^ 1011 0110(13 ^ 11 = 6)
位取非 ~ 对二进制表示的每一位数字进行取反。 ~1101 0010(假设操作在4位上,~13 = 2)
左移 << 将二进制位左移指定的位数,低位补0。 0011 << 2 1100(3 << 2 = 12)
右移 >> 将二进制位右移指定的位数,高位根据符号位填充。 1110 >> 1 1111(-2 >> 1 = -1,假设操作在4位上)
无符号右移 >>> 将二进制位右移指定的位数,高位补0。 11100101 >>> 3 00011100(-27 >>> 3 = 536870902,假设32位)

3. 原码、反码与补码

在计算机中,负数是通过原码、反码和补码来表示的。这些方法影响着数值的存储方式及运算效率。了解这些概念是理解计算机如何处理负数的关键。

3.1 原码

原码是最简单的表示方法。它的最高位是符号位,0表示正数,1表示负数。其余位表示数字的大小。

举个栗子:

  • +7的原码:00000111
  • -7的原码:10000111

原码的优点是简单易懂,缺点是对于运算来说比较复杂,不方便进行加减运算,特别是当正负数混合时更为麻烦。

3.2 反码

反码同样最高位是符号位,0代表正数,1代表负数。其余位表示数值,与原码不同的是,负数的表示方法不同。负数的反码表示方法:将它的绝对值按位取反

举个栗子:

  • +7的反码:00000111
  • -7的反码:11111000

反码的优点是对于加减运算来说比原码简单,特别是当正负数混合时更简单,但缺点是在进行乘除运算时会出现问题。

3.3 补码

补码是现代计算机最常用的负数表示方法。补码同样最高位是符号位,0代表正数,1代表负数。其余位表示数值,其表示方法不同于原码和反码。补码解决了反码的不足,使得加减法运算变得更加简单高效。负数的补码表示方法:将其绝对值的二进制表示取反,然后加上1

举个栗子:

  • +7的补码:00000111
  • -7的补码:11111001

补码不仅能简化加减法运算,还能避免符号位带来的问题。

小结

类型 描述 正数示例 负数示例 特点
原码 最高位为符号位,0表示正,1表示负,其余位表示数值。 +7: 0000 0111 -7: 1000 0111 简单,但正负数加减法操作复杂
反码 正数的反码与原码相同,负数的反码为其原码除符号位外各位取反。 +7: 0000 0111 -7: 1111 1000 解决了0的表示问题,简化了加减法
补码 正数的补码与原码相同,负数的补码为其反码加1。 +7: 0000 0111 -7: 1111 1001 计算机内部普遍使用,优化了运算效率

4. 最后

希望对你有帮助,一起努力,共同进步!

另外给喜欢记笔记的同学安利一款好用的云笔记软件,对比大部分国内的这个算还不错的,免费好用::wolai

相关推荐
闻缺陷则喜何志丹10 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
Lenyiin28 分钟前
01.02、判定是否互为字符重排
算法·leetcode
鸽鸽程序猿44 分钟前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd44 分钟前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v1 小时前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神2 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人2 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法