从集合论到位运算

前言


本文将扫清位运算的迷雾,在集合论与位运算之间建立一座桥梁。

在高中,我们学了集合论(set theory)的相关知识。例如,包含若干整数的集合 S={0,2,3}。在编程中,通常用哈希表(hash table)表示集合。例如 Java 中的 HashSet,C++ 中的 std::unordered_set。

在集合论中,有交集 ∩、并集 ∪、包含于 ⊆等等概念。如果编程实现「求两个哈希表的交集」,需要一个一个地遍历哈希表中的元素。那么,有没有效率更高的做法呢?

该二进制登场了。

集合可以用二进制表示,二进制从低到高第 i 位为 1表示 i 在集合中,例如集合{0,2,3}可以用二进制1101表示;反过来,1101就对应集合{0,2,3}。正式地说,包含非负整数的集合S可以用以下方式压缩成一个数字:

                                                       f(S) = \sum_{i\in s}^{} 2^i

例如集合{0,2,3}可以压缩成2^0 + 2^2 + 2^3 = 13也就是二进制的1101。

利用位运算「并行计算」的特点,我们可以高效地做一些和集合有关的运算。按照常见的应用场景,可以分为以下四类:

  1. 集合与集合
  2. 集合与元素
  3. 遍历集合
  4. 枚举集合

一、集合与集合


其中 & 表示按位与,∣ 表示按位或,⊕ 表示按位异或,∼ 表示按位取反。

两个集合的「对称差」是只属于其中一个集合,而不属于另一个集合的元素组成的集合,也就是不在交集中的元素组成的集合。

术语集合位运算集合示例位运算示例
交集A∩Ba&b{0,2,3}∩{0,1,2} = {0,2}1101 & 0111 = 0101
并集A∪Ba ∣ b{0,2,3}∪{0,1,2} = {0,1,2,3}1101 | 0111 = 1111
对称差A Δ Ba⊕b{0,2,3}Δ{0,1,2} = {1,3}1101 ⊕ 0111 = 1010
A\Ba&∼b{0,2,3}\{1,2} = {0,3}1101 & 1001 = 1001

二、集合与元素

通常会用到移位运算。

其中 << 表示左移,>> 表示右移。

术语集合位运算集合示例位运算示例
空集0
单元素集合{i}1<<i{2}1<<2
全集U={0,1,2,⋯n−1}(1<<n)-1{0,1,2,3}(1<<4)-1
补集Cu​S=U\S((1<<n)-1)⊕sU={0,1,2,3}
Cu{1,2}={0,3}
1111 ⊕ 0110 = 1001
属于i \in S(s >> i) & 1=12 \in [{0,2,3}](1101 >> 2) & 1=1
不属于i \notin S(s >> i) & 1=01\notin [0,2,3](1101 >> 1) & 1=0
添加元素S∪{i}s | (1<<i){0,3}∪{2}1001 ∣ (1 << 2)
删除元素S \ {i}s&∼(1 << i){0,2,3}\{2}1101&∼(1 << 2)

特别地,如果 𝑠 是 2 的幂,那么 𝑠 &( 𝑠 − 1) =0。

此外,编程语言提供了一些和二进制有关的库函数,例如:

  • 计算二进制中的 1 的个数,也就是集合大小;
  • 计算二进制长度,减一后得到集合最大元素;
  • 计算二进制尾零个数,也就是集合最小元素。

三、遍历集合

设元素范围从0到n-1,挨个判断每个元素是否在集合s中

for (int i = 0; i < n; i++) {
    if ((s >> i) & 1) { // i 在 s 中
        // 处理 i 的逻辑
    }
}

四、枚举集合

枚举所有集合

设元素范围从 0 到 n−1,从空集 ∅ 枚举到全集 U:

for (int s = 0; s < (1 << n); s++) {
    // 处理 s 的逻辑
}

枚举非空子集

设集合为 𝑠,从大到小枚举 𝑠 的所有非空子集 sub:

for (int sub = s; sub; sub = (sub - 1) & s) {
    // 处理 sub 的逻辑
}

为什么要写成 sub = (sub - 1) & s 呢?

暴力做法是从s开始,不断减一,直到0但这样做,中途会遇到很多不是s的子集的情况。例如s=10101时,减1得到10100,这是s的子集,但是再减1就得到10011了。这并不是s的子集。下一个子集应该是10001。

把所有的合法子集按顺序列出来,会发现我们做的相当于「压缩版」的二进制减法,例如

                                10101→10100→10001→10000→00101→⋯

如果忽略掉 10101 中的两个 0,数字的变化和二进制减法是一样的,即

                                        111→110→101→100→011→⋯

如何快速跳到下一个子集呢?比如,怎么从 10100 跳到 10001?

  • 普通的二进制减法,是10100-1=10011,也就是把最低位的1变成0,对于最低位的1右边的0都变成1。
  • 压缩版的二进制减法也是类似的,对于10100->10001,也会把最低位的1变成0,对于最低位的1右边的0,并不是都变成1,只有在s=10101中的1才会变成1。怎么做到?减1后&10101就行,也就是(10100-1)&10101 = 10001

枚举子集(包含空集)

如果要从大到小枚举 𝑠 的所有子集 sub(从 𝑠 枚举到空集 ∅),可以这样写:

int sub = s;
do {
    // 处理 sub 的逻辑
    sub = (sub - 1) & s;
} while (sub != s);

原理是当sub=0时(空集),再减1就得到-1,对应的二进制位111...1,在&s就得到了s,所以循环到sub=s时,说明最后一次循环sub=0(空集),s的所有子集都枚举到了。退出循环。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络学习2

文章目录 信道复用技术 第三章数据链路层概述数据链路层的三个重要问题封装成帧和透明传输差错检测可靠传输的相关基本概念可靠传输的实现机制停止等待协议回退N帧协议选择重传协议 点对点协议PPP共享式以太网网络适配器和MAC地址CSMA_CD协议的基本原理共享式以太网的争用期共享…

【计算机毕业设计】331基于微信小程序的家庭财务管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

开源VS闭源:大模型发展路径之争,你站哪一派?

文章目录 引言一、数据隐私1.1开源大模型的数据隐私1.2 闭源大模型的数据隐私1.3 综合考量 二、商业应用2.1 开源大模型的商业应用2.2 闭源大模型的商业应用2.3 商业应用的综合考量 三、社区参与3.1 开源大模型的社区参与3.2 闭源大模型的社区参与3.3 综合考量 结论 引言 在人…

数据库与数据库管理系统 MySQL的安装 SQL语言学习:DDL、DML

day51 数据库 数据库&#xff08;database&#xff09;就是一个存储数据的仓库。为了方便数据的存储和管理&#xff0c;它将数据按照特定的规律存储在磁盘上。 通过数据库管理系统&#xff0c;可以有效地组织和管理存储在数据库中的数据&#xff0c;如数据库管理系统MySQL 数据…

html three.js 引入.stl模型示例

1.新建一个模块用于放置模型 <div id"chart_map" style"width:800px;height:500px"></div> 2. 引入代码根据需求更改 <!-- 在head或body标签内加入以下链接 --> <script src"https://cdn.jsdelivr.net/npm/three0.137/build/t…

c++的string一键介绍

前言&#xff1a; 这篇文章旨在帮助读者回忆如何使用string&#xff0c;并提醒注意事项。它不是一篇详细的功能介绍&#xff0c;而是一篇润色文章。 先展示重载函数&#xff0c;如果该函数一笔不可带过&#xff0c;就先展示英文原档&#xff08;附带翻译&#xff09;&#xf…

基于语音信号MFCC特征提取和GRNN神经网络的人员身份检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 MFCC特征提取 4.2 GRNN神经网络概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ...............................................…

Django序列化器中is_valid和validate

今天上班的时候分配了一个任务&#xff0c;是修复前端的一个提示优化&#xff0c;如下图所示&#xff1a; 按照以往的经验我以为可以直接在validate上进行校验&#xff0c;如何抛出一个异常即可 &#xff0c;例如&#xff1a; class CcmSerializer(serializers.ModelSerialize…

HALCON-从入门到入门-软件界面介绍

1.废话 从halcon12到halcon23&#xff0c;开发的IDE界面大差不差&#xff0c;简单说下界面上不同功能按键的分布&#xff0c;以及一些快捷键啥的&#xff0c;要是还有我没有总结到的&#xff0c;又比较好用的&#xff0c;欢迎大家补充一下。 1.菜单栏 从上看到下&#xff0c;…

大型医疗器械企业四套系统数据集成技术干货分享

在大型医疗企业中&#xff0c;数据的互联互通是提升运营效率和数据利用率的关键。本次分享将概述如何通过轻易云集成平台将金蝶ERP、ZOHO CRM、泛微OA和汇联易报销系统进行高效联动&#xff0c;展示在实施过程中积累的技术干货。 某大型医疗企业&#xff0c;专注于麻醉和呼吸医…

系统架构设计师 - 操作系统(1)

操作系统 操作系统&#xff08;5-6分&#xff09;操作系统概述进程管理进程和线程的基本概念进程的状态 ★前趋图 ★★★★信号量与 PV 操作 ★★★★死锁及银行家算法 ★ 大家好呀&#xff01;我是小笙&#xff0c;本章我主要分享系统架构设计师 - 操作系统(1)知识&#xff0c…

B站如何屏蔽短视频:成都鼎茂宏升文化传媒公司

B站如何屏蔽短视频&#xff1a;优化你的观看体验 在当今数字化时代&#xff0c;B站&#xff08;哔哩哔哩&#xff09;作为国内领先的弹幕视频网站&#xff0c;以其丰富的视频资源和独特的弹幕文化吸引了大量用户。然而&#xff0c;随着短视频的兴起&#xff0c;B站也引入了短视…

智能学工系统实现学生管理

人才培养是高校的榜首要务&#xff0c;高校在抓好学生教育作业的一起&#xff0c;更多的是要加强对学生的办理作业。作为在校大学生健康成长的指导者和引路人&#xff0c;面临很多的学生办理作业内容杂乱&#xff0c;事无巨细&#xff0c;但在传统的办理方式下&#xff0c;尽管…

在 LLM 架构中应用多专家模型

本文转载自&#xff1a;在 LLM 架构中应用多专家模型 2024年 3月 14日 By Kyle Kranen and Vinh Nguyen https://developer.nvidia.cn/zh-cn/blog/applying-mixture-of-experts-in-llm-architectures/ 文章目录 一、概述二、LLM 架构领域的专家齐聚一堂1、模型容量2、MoE 在降低…

计算机系统结构之Cache

一、全相联映像和变换 全相联映像的主存-Cache地址变换过程如图&#xff1a; 给出主存地址Nm访存时&#xff0c;将其主存块号Nmb与目录表(硬件)中所有各项的Mmb字段同时相联比较。若有相同的&#xff0c;就将对应行的Cache块号Ncb取出&#xff0c;拼接上块内地址Nmr形成Cache地…

JAVA基础|多线程

什么是线程&#xff1f; 线程&#xff08;Thread&#xff09;是一个程序内部的一条执行流程。 多线程是什么&#xff1f; 多线程是指从软硬件上实现的多条执行流程的技术&#xff08;多条线程由CPU负责调度执行&#xff09; 一. 如何在程序中创建出多条线程&#xff1f; Ja…

社交媒体数据恢复:Voxer

一、Voxer数据恢复教程 了解Voxer应用 Voxer是一款专门为iPhone和Android智能手机设计的免费对讲机应用&#xff0c;为用户提供即时的语音、文本、照片等信息发送和接收服务。该应用有点类似短信服务&#xff0c;但用声音代替文本。当你下载之后&#xff0c;如果不邀请朋友&a…

XTuner 微调个人小助手认知实战

XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。GitHub - InternLM/xtuner: An efficient, flexible and full-featured toolkit for fine-tuning LLM (InternLM2, Llama3, Phi3, Qwen, Mistral, ...)An efficient, flexible and full-featured toolkit for fine-tun…

vue中使用svg图像

一 、svg图像是什么 SVG&#xff08;可缩放矢量图形&#xff09;是一种图像格式&#xff0c;它以XML文档的形式存在&#xff0c;用以描述图像中的形状、线条、文本和颜色等元素。由于其基于矢量的特性&#xff0c;SVG图像在放大或改变尺寸时能够保持图形质量不受影响。这种格式…

【深入学习Redis丨第二篇】Redis集群部署详解

文章目录 Redis集群部署Redis4 Cluster部署 Redis集群部署 1 Redis各节点部署 使用源码安装各节点&#xff0c;不过与非cluster方式不同的是&#xff0c;配置文件中需启动cluster相关的配置。 因本次为伪分布式部署&#xff0c;生产环境部署时建议至少3台机器部署&#xff0…