位运算:带带孩子吧,孩子很强的!

news2024/9/20 0:42:16

在这里插入图片描述

快速进制

在聊到位运算之前,不妨先简单过一遍二进制的东西。熟悉二进制和十进制的快速转换确实是掌握位运算的基础,因为位运算直接在二进制位上进行操作。如果不熟悉二进制表示,很难直观理解位运算的效果。

这里主要涉及二进制和十进制之间的互相转换。


十进制转二进制

十进制转二进制可以使用常见的 除2取余法 进行。每次将十进制除以2并记录所得余数,直到商为0,然后再将记录的余数 从下往上排列即可得到对应的二进制。

将十进制 13 转为二进制:

  • 13 ÷ 2 = 6 余 1 13 ÷ 2 = 6 余 1 13÷2=61
  • 6 ÷ 2 = 3 余 0 6 ÷ 2 = 3 余 0 6÷2=30
  • 3 ÷ 2 = 1 余 1 3 ÷ 2 = 1 余 1 3÷2=11
  • 1 ÷ 2 = 0 余 1 1 ÷ 2 = 0 余 1 1÷2=01

将上面的余数从下往上排得到1101就是13对应的二进制了;是不是so easy too happy!


二进制转十进制

从右往左每一位乘以对应2的幂,然后求和即可;

将二进制1011 转为对应十进制;

  • 1 × 2³ = 8
    0 × 2² = 0
  • 1 × 2¹ = 2
  • 1 × 2⁰ = 1

求和:8 + 0 + 2 + 1 = 1111即为1011的十进制表示;

这些是常规的计算方法,可能大部分人在开始学习的时候多少都接触过,但我们的诉求是尽可能的通过心算的方式快速进行二进制十进制之间的转换,这样才能在使用位运算时得心应手。下面就介绍一下如何练习以及一些常用的技巧;


1248原则

1248原则是一个快速进行二进制到十进制转换的技巧,主要用于帮助我们快速计算二进制数对应的十进制值。这一原则来源于二进制的基本权值,也就是每一位二进制数字代表的2的幂次方值。

从右向左,二进制的各个位的值分别对应着:

  • 第一位:2⁰ = 1
  • 第二位:2¹ = 2
  • 第三位:2² = 4
  • 第四位:2³ = 8

继续向左,依次是16、32、64、128等。

所以1248代表了二进制数前四位的权重:1、2、4、8

当你看到一个二进制数时,可以直接用“1248”来快速确定前几位的权重值,从而进行快速的心算。

例如,转换二进制数 1011 到十进制:

  1. 首先使用

    1248

    原则标记每一位的权值:

    • 最右边一位(1):代表 1
    • 第二位(1):代表 2
    • 第三位(0):代表 4
    • 第四位(1):代表 8
  2. 然后将这些有值的位加起来:1 + 2 + 8 = 11 因此,二进制 1011 对应的十进制数是 11

再举一个例子: 二进制数 11010

  1. 应用 1248原则,最右边开始的前四位的权值是

    1、2、4、8

    ,第五位是16:

    • 最右边第一位是0,代表的值是0
    • 第二位是1,代表的值是2
    • 第三位是0,代表的值是0
    • 第四位是1,代表的值是8
    • 第五位是1,代表的值是16
  2. 将这些有值的位加起来: 16 + 8 + 2 = 26

所以,二进制 11010 对应的十进制数是 26


其他常用技巧

  • 熟记常见的2的幂,这样可以帮你快速推断数值,如(2⁰ = 1,2¹ = 2,2² = 4,2³ = 8,2⁴ = 16,2⁵ = 32...),这可以帮助你快速判断十进制数字在哪个幂次范围内,并由此快速推导出二进制。
  • 熟记小范围内的特殊值,记住一些常见的二进制值,可以进行快速映射。例如:

1111 = 15, 1010 = 10, 1001 = 9, 0111 = 7 等常用值。如果遇到类似的值,可以直接推导,而不需要逐位计算。

  • 如果数字接近2的幂次方,可以快速得到前几位。比如 14 接近 2⁴ = 16,因此前面部分是 1110,只需要从16减去14推导出最后两位的变化。

  • 对于10、100、1000等特殊数字的二进制:这些数字的二进制可以直接记忆,心算时直接转换。

    • 10 的二进制:1010
    • 100 的二进制:1100100
    • 1000 的二进制:1111101000
  • 当遇到大数字时,可以通过分解法来加快心算速度。例如,将一个大数分成几个较小的数字,每个数字转换成二进制后再合并。

    • 例如:75 转为二进制,可以将其分为64(2⁶)+ 8(2³)+ 2(2¹)+ 1(2⁰):
      • 64 的二进制是 1000000
      • 8 的二进制是 1000
      • 2 的二进制是 10
      • 1 的二进制是 1
      • 最终结果为 1001011

位运算

使用位运算之前,务必先熟悉下面的几个运算规则:

与运算(&):将两个数按位进行“与”操作,只有对应位都是1时结果才为1,否则为0。

或运算(|):将两个数按位进行“或”操作,任意一位为1时结果为1,否则为0。

异或运算(^):将两个数按位进行“异或”操作,相同为0,不同为1。

非运算(~):对数值按位取反,0变1,1变0。

左移(<<):将二进制位向左移动n位,相当于乘以2^n。

右移(>>):将二进制位向右移动n位,相当于除以2^n(有符号时保留符号位)。


对应上面的规则,下面通过简单的示例体验一下:

#include <iostream>
using namespace std;

int main() {
    int A = 12;  // 二进制: 1100
    int B = 10;  // 二进制: 1010

    // 1. 与运算(&)
    int andResult = A & B;  // 结果: 8  (二进制: 1000)
    cout << "A & B = " << andResult << endl;

    // 2. 或运算(|)
    int orResult = A | B;  // 结果: 14 (二进制: 1110)
    cout << "A | B = " << orResult << endl;

    // 3. 异或运算(^)
    int xorResult = A ^ B;  // 结果: 6  (二进制: 0110)
    cout << "A ^ B = " << xorResult << endl;

    // 4. 非运算(~)
    int notResult = ~A;  // 结果: -13 (按位取反后的二进制表示: 11111111111111111111111111110011)
    cout << "~A = " << notResult << endl;

    // 5. 左移运算(<<)
    int leftShift = A << 2;  // A 向左移 2 位,结果: 48  (二进制: 110000)
    cout << "A << 2 = " << leftShift << endl;

    // 6. 右移运算(>>)
    int rightShift = A >> 2;  // A 向右移 2 位,结果: 3  (二进制: 0011)
    cout << "A >> 2 = " << rightShift << endl;

    return 0;
}

实际应用

为什么会突然想到写这么一篇文章也不是突发奇想。主要是最近在游戏开发过程中遇到了一个常见的需求,比如游戏界面的红点系统。由于判定一个界面是否需要显示红点,这些逻辑需要后端去处理,然后返回一个是否显示的标记给前端进行具体的渲染流程。

实现这个需求的方法很多,比较常见的做法是后端处理完之后将红点状态以表的形式存起来再通过请求发送到前端,但是这样做会加大前后端交互过程中数据传输的数据量,可能会导致数据传输超上限、服务器压力增加、后端计算成本提高等潜在的问题,毕竟一个游戏功能的界面的红点数是有可能多达几十上百个的,而且每次都需要后端不断的进行存表读表的操作,确实不够优雅。

所以才想到基于二进制特有的01标记来作为状态标志位,使用位运算实现一个高效简洁的红点效果。

通过使用位运算,我们只需要将每个位置对应的红点位置为1,不显示红点时置为0即可,而在向前端传输红点状态数据时就不需要来传表结构的数据了,只需要一个简单的十进制阿拉伯数字即可,将该传输传到前端结果位运算简单的解析之后即可获得红点状态信息。

上面只是一部分应用,其实在实际开发中,还有很多地方可以用到位运算,或者是使用位运算提高性能,简化代码的地方。比如

状态标志位

在嵌入式开发、游戏开发、网络通信等场景中,经常需要用位表示多个状态(如开关、错误标志)。通过位运算可以快速检查和设置这些状态。比如上面的红点系统。

const int FLAG_A = 1 << 0;  // 0001
const int FLAG_B = 1 << 1;  // 0010
const int FLAG_C = 1 << 2;  // 0100

int flags = FLAG_A | FLAG_C;  // 具有 FLAG_A 和 FLAG_C 的状态

// 检查 FLAG_B 是否设置
if (flags & FLAG_B) {
    cout << "FLAG_B is set" << endl;
} else {
    cout << "FLAG_B is not set" << endl;
}

应用场景:设备状态监控、通信协议标志。


数据压缩

位运算用于将多个小数值打包在一个更大的数据类型中,节省空间。例如,在图像处理、视频编码等领域,经常通过位运算来压缩颜色、透明度等多个通道的数据。

unsigned int color = (255 << 24) | (128 << 16) | (64 << 8) | 32;
// 将 RGBA 值分别存储在 32 位整数的不同段

哈希运算和校验

在哈希表实现、数据加密、CRC 校验中,位运算可以加速特定运算,避免浮点数操作,提高性能。

示例:
cppCopy codeunsigned int hashFunction(unsigned int x) {
    return x ^ (x >> 16);  // 异或和右移结合生成哈希
}

位图/布隆过滤器

位运算用于表示集合或快速查找元素是否存在。位图通过每一位表示一个元素是否存在,布隆过滤器则使用多个哈希函数来进行快速查找。

const int SIZE = 100;
int bitmap[SIZE / 32] = {0};  // 位图数组,每32位存储一个int

void setBit(int index) {
    bitmap[index / 32] |= (1 << (index % 32));  // 设置位
}

bool getBit(int index) {
    return bitmap[index / 32] & (1 << (index % 32));  // 检查位
}


高效计算(高频常用)

位运算可以代替乘法、除法、模运算,奇偶性判断等操作,提高效率,尤其在性能敏感的嵌入式系统、图形编程中广泛使用。

int x = 16;
int y = x << 1;  // x * 2
int z = x >> 1;  // x / 2

// 判断奇偶性
number & 1 == 0 // 偶数
number & 1 == 1 // 奇数    

循环队列/环形缓冲区

使用位运算来快速处理循环队列的索引更新,尤其在队列的大小是2的幂时,可以通过与运算快速获取索引的值。

const int SIZE = 8;  // 大小为2的幂
int buffer[SIZE];
int head = 0;
int tail = 0;

void enqueue(int value) {
    buffer[tail] = value;
    tail = (tail + 1) & (SIZE - 1);  // 位运算获取下一个索引
}

小结

可以的话,多用用位运算吧,这孩子还是很强的!

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

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

相关文章

蓝桥杯嵌入式国三备赛经验分享

1 学习STM32入门视频 向大家推荐一套宝藏级别的视频&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 如果已经比过蓝桥杯单片机或学习过单片机相关课程的同学&#xff0c;你们可以尝试不需要STM32套件进行学习。如果没有学过单片机相关课程的同学&#xff0c;可以买…

直击智博会,supOS加快发展新质生产力,赋能全球工厂数字化转型

9月6日&#xff0c;第十四届智慧城市与智能经济博览会&#xff08;以下简称智博会&#xff09;开幕主题活动在宁波举办。本届智博会着重围绕“数字赋能新型工业化”主题&#xff0c;设置开幕活动、展览展示和前瞻研讨、产数合作、赛事赋能、开放活动等4大板块活动&#xff0c;旨…

全球AI产品Top100排行榜

Web Top50的榜单里&#xff0c;AIGC类型的应用占比52%&#xff0c;遥遥领先。AIGC类型包括图像、视频、音乐、语音等的内容生成和编辑。音乐生成应用Suno在过去六个月中的排名跃升最为显著&#xff0c;从第36位上升至第5位。排名第二大类是通用对话/AI聊天/角色扮演类型的应用&…

银河麒麟系统开机自动进入指定账户(如:root)桌面

目录 1. 需求的提出 2. 机器环境说明 3. 解决方法 4. 附加说明 1. 需求的提出 编写好的软件在客户的装有银河麒麟操作系统的机器上运行&#xff0c;但有些操作必须用root权限才能操作&#xff0c;如&#xff1a;打开串口。Linux下的普通账户打开串口时提示权限不足。在普通…

【HarmonyOS NEXT】实现截图功能

【HarmonyOS NEXT】实现截图功能 【需求】 实现&#xff1a;实现点击截图按钮&#xff0c;实现对页面/组件的截图 【步骤】 编写页面UI Entry Component struct Screenshot {BuildergetSnapContent() {Column() {Image().width(100%).objectFit(ImageFit.Auto).borderRadi…

C++入门(06)安装QT并快速测试体验一个简单的C++GUI项目

文章目录 1. 清华镜像源下载2. 安装3. 开始菜单上的 QT 工具4. 打开 Qt Creator5. 简单的 GUI C 项目5.1 打开 Qt Creator 并创建新项目5.2 设计界面5.3 添加按钮的点击事件5.4 编译并运行项目 6. 信号和槽&#xff08;Signals and Slots&#xff09; 这里用到了C类与对象的很多…

网络协议详解

目录 1.认识网络协议 2网络协议的设计 2.1网络通信的问题 2.2网络协议的分层设计 软件分层与网络分层 3.OSI七层网络模型 各层次的介绍如下 4.TCP/IP 五层协议 各层次说明 各层次所解决的问题 5.网络和操作系统之间的关系 单主机下 多主机下 6.重新理解网络协议 …

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数 一、环境说明二、页面之间相互传参 一、环境说明 DevEco Studio 版本&#xff1a; API版本&#xff1a;以12为主 二、页面之间相互传参 说明&#xff1a; 页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页…

kubernetes微服务基础及类型

目录 1 什么是微服务 2 微服务的类型 3 ipvs模式 ipvs模式配置方式 4 微服务类型详解 4.1 ClusterIP 4.2 ClusterIP中的特殊模式headless 4.3 nodeport 4.4 metalLB配合loadbalance实现发布IP 1 什么是微服务 用控制器来完成集群的工作负载&#xff0c;那么应用如何暴漏出去&…

JavaWeb——JavaScript(3/4)-JS对象:BOM、DOM(Window、Location,概念、标准模型、获取元素对象)

目录 BOM 介绍 Window 案例(1) Location DOM 概念 标准模型 获取元素对象 案例(2) 原始代码 完整代码 JS对象 BOM 介绍 概念&#xff1a;Browser Object Model 浏览器对象模型&#xff0c;允许JavaScript与浏览器对话&#xff0c;JavaScript 将浏览器的各个组成部…

git 提交自动带上storyid

公司里的运维团队的产品经理&#xff0c;那老六提出说要在每个提交带上的jira storyid或者bugid&#xff0c;不用他自己弄不顾他人麻烦&#xff0c;真想问候他的xx。不过既然已经成为定局&#xff0c;还是想想有没有其他办法。经一番调研&#xff0c;网上有比较零碎的信息&…

攻防世界--->地穴

前言&#xff1a;学习笔记。 下载 解压 查壳。 64位ida打开。 进入主函数。 很容易得知&#xff0c;这是一个RC4加密。 【 &#xff08;题外话&#xff09; 在reverse中&#xff0c;RC4考点&#xff0c;不会很难。 reverse中RC4关键点就是&#xff0c;抓住异或。 一般解这种…

Open a folder or workspace... (File -> Open Folder)

问题&#xff1a;vscode Open with Live Server 时 显示Open a folder or workspace... (File -> Open Folder)报错 解决&#xff1a;不可以单独打开文件1.html ; 需要在文件夹里打开 像这样

【哈希表】深入理解哈希表

目录 1、哈希表简介2、哈希函数2.1、概念2.2、常用的哈希函数2.2.1、直接定址法2.2.2、除留余数法2.2.3、平方取中法2.2.4、基数转换法 3、哈希冲突3.1、概念3.2、开放地址法【闭散列&#xff1a;key存放到冲突位置的“下一个”空位置】3.3、链地址法【开散列&#xff1a;冲突位…

SAM 2:分割图像和视频中的任何内容

文章目录 摘要1 引言2 相关工作3 任务&#xff1a;可提示视觉分割4 模型5 数据5.1 数据引擎5.2 SA-V数据集 6 零样本实验6.1 视频任务6.1.1 提示视频分割6.1.2 半监督视频对象分割6.1.3 公平性评估 6.2 图像任务 7 与半监督VOS的最新技术的比较8 数据和模型消融8.1 数据消融8.2…

dr 航迹推算 知识介绍

DR&#xff08;Dead Reckoning&#xff09;航迹推算是一种在航海、航空、车辆导航等领域中广泛使用的技术&#xff0c;用于估算物体的位置。DR航迹推算主要通过已知的初始位置和运动参数&#xff08;如速度、方向&#xff09;来预测物体的当前位置。以下是 DR 航迹推算的详细知…

跨平台电商数据整合:item_get API在电商大数据平台中的角色

在电商行业蓬勃发展的今天&#xff0c;跨平台运营已成为众多商家的必然选择。然而&#xff0c;随之而来的数据孤岛问题却成为了制约电商企业进一步发展的瓶颈。为了解决这一问题&#xff0c;电商大数据平台应运而生&#xff0c;而item_get API作为获取商品详情的关键接口&#…

统计学第6天

1、变量间关系的度量 函数关系 &#xff08;1&#xff09;是一一对应的确定关系&#xff1b; &#xff08;2&#xff09;设有两个变量x和y&#xff0c;变量y随x一起变化&#xff0c;并完全依赖于x,当x取某个数值时&#xff0c;y根据确定的关系取相应的值&#xff0c;称y是x的…

建设网盘聚合中心—Win10+Alist+RaiDrive

经常需要在网上找各种资源&#xff0c;但遇到 2 个问题&#xff1a; 1. 大部分网盘都需要先将文件保存在自己网盘后才能下载&#xff0c;也就是必须创建对应网盘账号。 2. 有些网盘还必须要下载客户端才能下载文件。 创建账号无法避免&#xff0c;但可以不用下载那么多的客户端…

写在 Pencils Protocol TGE 前:加密市场共识才是王道,拥抱社区

“Pencils Protocol 正在成为本轮市场周期中&#xff0c;加密项目建立共识最有力的工具&#xff01;” 对于加密项目而言&#xff0c;代币 TGE 是一个非常重要的事情&#xff0c;它不仅仅意味着生态内经济系统的全面启动&#xff0c;同时也意味着项目生态市场的全面开启。当然…