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

在这里插入图片描述

快速进制

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

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


十进制转二进制

十进制转二进制可以使用常见的 除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;  // 二进制: 1100int 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;  // 0100int 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位存储一个intvoid 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.rhkb.cn/news/418925.html

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

相关文章

Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题 缓存穿透是指查询一个一定不存在的数据&#xff0c;由于缓存中没有命中&#xff0c;会去数据库中查询&#xff0c;而数据库中也没有该数据&#xff0c;并且每次查询都不会命中缓存&#xff0c;从而每次请求都直接打到了数据库上&#xff0c;这会给数据…

django ubuntu 踩坑集锦

目录 1 ubantu mysql查看表结构2 导入同级目录文件出现未解析引用错误3 第三方包——tinymce富文本编辑器4 verbose_name,verbose_name_plural5 搜索路径的添加6 auto_now_add 和 auto_now7 auth_user的表结构8 在 Django 中定义 ForeignKey 字段时&#xff0c;必须指定 on_del…

前端登录鉴权——以若依Ruoyi前后端分离项目为例解读

权限模型 Ruoyi框架学习——权限管理_若依框架权限-CSDN博客 用户-角色-菜单&#xff08;User-Role-Menu&#xff09;模型是一种常用于权限管理的设计模式&#xff0c;用于实现系统中的用户权限控制。该模型主要包含以下几个要素&#xff1a; 用户&#xff08;User&#xff09;…

全倒装COB超微小间距LED显示屏的工艺技术,相比SMD小间距有何优势

全倒装COB&#xff08;Chip On Board&#xff09;超微小间距LED显示屏&#xff0c;在工艺技术上的革新&#xff0c;相较于传统的SMD&#xff08;Surface Mount Device&#xff09;小间距LED显示屏&#xff0c;展现出了多方面的显著优势。 首先&#xff0c;全倒装技术极大地提升…

【踩坑】Vue3项目正常跑动后页面空白问题

近期踩了个坑&#xff0c;Vue3搭建的项目能够正常跑动&#xff0c;但是页面却是空白的&#xff0c;控制台也不报错&#xff0c;只留下一行警告&#xff1a; 发现是 router 入口文件&#xff08;一般是在 router 文件夹下的 index 里面&#xff09;的写法和 vite 版本不匹配的问…

代码随想录 刷题记录-24 图论 (1)理论基础 、深搜与广搜

一、理论基础 参考&#xff1a; 图论理论基础 深度优先搜索理论基础 广度优先搜索理论基础 dfs dfs搜索可一个方向&#xff0c;并需要回溯&#xff0c;所以用递归的方式来实现是最方便的。 有递归的地方就有回溯&#xff0c;例如如下代码&#xff1a; void dfs(参数) {…

基于 RocketMQ 的云原生 MQTT 消息引擎设计

作者&#xff1a;沁君 概述 随着智能家居、工业互联网和车联网的迅猛发展&#xff0c;面向 IoT&#xff08;物联网&#xff09;设备类的消息通讯需求正在经历前所未有的增长。在这样的背景下&#xff0c;高效和可靠的消息传输标准成为了枢纽。MQTT 协议作为新一代物联网场景中…

QT+OSG+osg-earth显示一个球

目录 1、环境配置 2、在QT Creator导入相关的库 3、代码部分 4、运行过程中的问题 5、相关参考 重要衔接&#xff1a;QTOSG显示一个三维模型-CSDN博客 1、环境配置 系统&#xff1a;windows10系统 QT:版本5.15.2 编译器&#xff1a;MSVC2019_64bit 编辑器…

unity 实现吸血鬼幸存者的随机奖励

设置奖励的数据类型 // // Auto Generated Code By excel2json // https://neil3d.gitee.io/coding/excel2json.html // 1. 每个 Sheet 形成一个 Struct 定义, Sheet 的名称作为 Struct 的名称 // 2. 表格约定&#xff1a;第一行是变量名称&#xff0c;第二行是变量类型// Gen…

DevC++编译及使用Opencv

1.依赖 需要如下依赖&#xff1a; DevC11Opencv4.10.0CMake.exe 整个安装过程参考下面的文章&#xff1a;https://blog.csdn.net/weixin_41673576/article/details/108519841 这里总结一下遇到的问题。 2.问题 2.1 DevC安装路径 一定不要有空格&#xff01;&#xff01;否则…

【自动驾驶】控制算法(八)横向控制Ⅲ | 代码与模型

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

Java | Leetcode Java题解之第393题UTF-8编码验证

题目&#xff1a; 题解&#xff1a; class Solution {static final int MASK1 1 << 7;static final int MASK2 (1 << 7) (1 << 6);public boolean validUtf8(int[] data) {int m data.length;int index 0;while (index < m) {int num data[index];…

从零开始学习JVM(七)- StringTable字符串常量池

1 概述 String应该是Java使用最多的类吧&#xff0c;很少有Java程序没有使用到String的。在Java中创建对象是一件挺耗费性能的事&#xff0c;而且我们又经常使用相同的String对象&#xff0c;那么创建这些相同的对象不是白白浪费性能吗。所以就有了StringTable这一特殊的存在&…

Python爬虫:通过js逆向获取某瓜视频的下载链接

爬虫:通过js逆向获取某瓜视频的下载链接 1. 前言2. 获取script标签下的视频加密数据3. 第一步:获取解密后的视频下载链接4. 第二步:模拟生成加密的webid值 1. 前言 就小编了解&#xff0c;某瓜视频这个网站对应视频下载链接加密处理至少经过三个版本。之前在CSDN发布了一篇关于…

华为 HCIP-Datacom H12-821 题库 (5)

有需要题库的可以看主页置顶 需要题库的加Q裙 V群仅进行学习交流 1.以下关于堆叠 MAD 检测说法错误的是&#xff1f; A、堆系统互为代理进行 MAD 检测时&#xff0c;两个堆系统可以使用相同的D omain ID B、MAD 检测的方式分为直连检测、代理检测 C、MAD 代理检测要求所有堆叠…

Vim笔记

【指尖飞舞&#xff1a;vscode vim 高效开发&#xff08;系列视频&#xff09;】https://www.bilibili.com/video/BV1z541177Jyp16&vd_source23e4761174881d73295e362ffd706749 Vscode vim插件配置-CSDN博客 g_跳到行尾最后一个非空字符 gd :go to definition ctrl (o): …

【基础】Three.js 自定义几何体和复制几何体

通过自定义顶点数据&#xff0c;可以创建任意的几何体。像threejs的长方体BoxGeometry、球体SphereGeometry等几何体都是基于BufferGeometry类构建的&#xff0c;它表示一个没有任何形状的空几何体。 1. 自定义点模型 通过javascript 类型化数组 Float32Array创建一组xyz坐标…

比特币客户端和API

1. 比特比客户端的安装 Bitcoin Core 客户端适用于从 x86 Windows 到 ARM Linux 的不同架构和平台&#xff0c;如下图所示&#xff1a; 2. Bitcoin Core客户端的类型 2.1 Bitcoind Bitcoind 末尾的字母 d 表示 daemon (守护程序&#xff09;。所谓守护程序&#xff0c;就是指常…

基于深度学习 卷积神经网络resnext50的中医舌苔分类系统

项目概述 本项目旨在通过深度学习技术&#xff0c;特别是利用卷积神经网络&#xff08;Convolutional Neural Networks, CNNs&#xff09;中的ResNeXt50架构&#xff0c;实现对中医舌象图像的自动分类。该系统不仅能够识别不同的舌苔类型&#xff0c;还能够在PyQt5框架下提供一…

简单实用的php全新实物商城系统

免费开源电商系统,提供灵活的扩展特性、高度自动化与智能化、创新的管理模式和强大的自定义模块,让电商用户零成本拥有安全、高效、专业的移动商城。 代码是全新实物商城系统源码版。 代码下载