✨1.1.1 按位与运算替代求余运算优化场景

在计算机编程中,使用按位与运算(&)替代求余运算(%)可以提高效率的特殊场景是:当除数是 2 的整数次幂(即 ( b = 2^n ),其中 ( n ) 为自然数)时。例如,( b = 2, 4, 8, 16, 32, 64 ) 等。此时,求余运算 ( a % b ) 可以等价转换为按位与运算 ( a & (b - 1) )。下面我将详细解释原理、运算过程、效率优势及适用场景。

为什么这种等价成立?

● 数学原理:当 ( b = 2^n ) 时,求余运算 ( a % b ) 的本质是获取 ( a ) 的二进制表示中的最低 ( n ) 位。因为:
○ ( b = 2n ) 的二进制形式是 1 后跟 ( n ) 个 0(例如,( 16 = 24 ) 的二进制是 10000)。
○ ( a ) 除以 ( b ) 时,高位的值被 ( b ) 整除,余数只取决于最低 ( n ) 位。
● 位运算原理:
○ ( b - 1 ) 的二进制形式是 ( n ) 个 1(例如,( 16 - 1 = 15 ) 的二进制是 01111)。
○ 按位与运算 ( a & (b - 1) ) 会保留 ( a ) 的最低 ( n ) 位,而将高位清零,这正好等于余数。
● 公式:
[
a % (2n) = a & (2n - 1)
]

详细运算过程(以 ( a = 23 ), ( b = 16 ) 为例)

  1. 求余运算 ( 23 % 16 ):
    ○ ( 23 ) 的二进制:10111(假设 5 位表示)。
    ○ ( 16 ) 是 ( 2^4 ),所以求余是取最低 4 位。
    ○ 计算:( 23 \div 16 = 1 ) 余 ( 7 )(因为 ( 16 \times 1 = 16 ), ( 23 - 16 = 7 ))。
    ○ 结果:( 7 )。
  2. 按位与运算 ( 23 & (16 - 1) = 23 & 15 ):
    ○ ( 23 ) 的二进制:10111。
    ○ ( 15 ) 的二进制:01111(( 16 - 1 = 15 ),即 4 个 1)。
    ○ 按位与操作(逐位比较,同 1 则 1,否则 0):
    23: 1 0 1 1 1
    & 15: 0 1 1 1 1

   0 0 1 1 1   → 二进制 `00111` = 十进制 7

○ 结果:( 7 ),与 ( 23 % 16 ) 相同。
关键点:
● 最低 4 位(0111)被保留,高位(10)被清零。
● 这等价于取 ( a ) 的二进制表示中的最低 ( n ) 位(这里 ( n = 4 ))。

为什么能提高效率?

  1. 硬件操作差异:
    ○ 求余运算 %:通常由 CPU 的除法指令实现,涉及多步计算(如减法、移位),开销较大(可能需要数十个时钟周期)。
    ○ 按位与运算 &:是 CPU 的单一指令,直接在位级别操作,通常只需 1 个时钟周期,速度极快。
  2. 优化效果:当 ( b ) 是 2 的次幂时,& 比 % 快 10 倍以上(具体取决于架构),尤其在循环或高频调用场景中(如哈希计算、位处理)。
    适用场景举例
  3. 哈希表桶索引计算:
    ○ 如果桶大小 ( \text{size} = 2^n )(如 32、64),计算索引:index = hash % size → index = hash & (size - 1)。
    ○ 例如:hash = 123, size = 32(( 2^5 )),则 123 % 32 = 27 等价于 123 & 31 = 27。
  4. 位掩码提取:
    ○ 提取颜色值(如 RGB 中的低 8 位):blue = color & 0xFF(等价于 color % 256)。
    ○ 检查奇偶性:a % 2 → a & 1(因为 ( 2 = 2^1 ),b - 1 = 1)。
  5. 环形缓冲区或循环队列:
    ○ 当缓冲区大小为 2 的次幂时,索引回绕:next_index = (current + 1) % buffer_size → next_index = (current + 1) & (buffer_size - 1)。

注意事项

● 严格条件:仅当 ( b = 2^n ) 时成立!如果 ( b ) 不是 2 的次幂(如 ( b = 10 )),则不能直接用 & 替代(需其他方法,如查表或乘法)。
● 负数处理:在编程语言中,% 和 & 对负数的行为可能不同(如 -7 % 16 可能为 -7 或 9,取决于语言)。建议先确保 ( a ) 为非负数,或使用位掩码强制转换。
● 编译器优化:现代编译器(如 GCC、Clang)在 b 为常量 2 的次幂时,可能自动将 % 转换为 &,但显式使用可确保优化。
总结
● 场景:当除数是 ( 2^n ) 时,用 ( a & (b - 1) ) 替代 ( a % b )。
● 原因:位运算直接提取二进制低位,避免昂贵的除法。
● 效率:& 是 O(1) 操作,远快于 % 的 O(log a) 复杂度。
通过这种优化,可以在底层系统编程、游戏开发、嵌入式系统等对性能敏感的领域显著提升速度。

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

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

相关文章

CentOS 7 环境中部署 LNMP(Linux + Nginx + MySQL 5.7 + PHP)

在 CentOS 7 环境中部署 LNMP(Linux Nginx MySQL 5.7 PHP) 环境的详细步骤如下。此方案确保各组件版本兼容,并提供完整的配置验证流程。 1. 更新系统 sudo yum update -y 2. 安装 MySQL 5.7 2.1 添加 MySQL 官方 YUM 仓库 由于MySQL并不…

UniApp微信小程序自定义导航栏实现

UniApp微信小程序自定义导航栏 在UniApp开发微信小程序时,页面左上角默认有一个返回按钮(在导航栏左侧),但有时我们需要自定义这个按钮的样式和功能,同时保持与导航栏中间的标题和右侧胶囊按钮(药丸屏&…

Java大师成长计划之第35天:未来展望与个人总结

引言 作为一门历史悠久的编程语言,Java自1995年问世以来,经历了多个版本的迭代与演进,依然在当今技术生态中占据着重要地位。从早期的Java SE、Java EE到后来的Java Spring框架,再到现代的微服务架构与云原生应用,Jav…

Ubuntu开机自动运行Docker容器中的Qt UI程序

Ubuntu开机自动运行Docker容器中的Qt UI程序 引言为什么需要这样配置?解决方案概览详细实现步骤1. 创建容器启动脚本2. 创建系统服务3. 配置自动登录和显示设置常见问题解决方案1. 程序无法显示(X11权限问题)2. 分辨率设置不生效3. 服务启动失败安全注意事项结语附录:完整文…

Scratch节日 | 龙舟比赛 | 端午节

端午节快乐! 这款专为孩子们打造的Scratch游戏——《龙舟比赛》,让你在掌控龙舟的竞速中,沉浸式体验中华传统节日的魅力! 🎮 游戏亮点 节日氛围浓厚:化身龙舟选手,在波涛汹涌的河流中展开刺激竞…

(五)MMA(OpenTelemetry/Rabbit MQ/ApiGateway/MongoDB)

文章目录 项目地址一、OpenTelemetry1.1 配置OpenTelemetry1. 服务添加2. 添加服务标识3. 添加请求的标识4. 添加中间价 二、Rabbit MQ2.1 配置Rabbit MQ1. docker-compose2. 添加Rabbit MQ的Connect String 2.2 替换成Rabbit MQ1. 安装所需要的包2. 使用 三、API Gateways3.1 …

格恩朗超声波水表 助力农业精准灌溉与振兴​

在农业现代化的征程中,水资源的精准利用至关重要,而这离不开高精度计量设备的支持。大连格恩朗品牌积极响应国家全面推进乡村振兴、加快农业农村现代化的号召,精心打造的超声波水表,凭借其超高精度,成为绿色灌溉领域的…

微信小程序页面嵌套web-view点击系统导航返回时进行弹窗处理

实现效果:微信小程序页面嵌套web-view点击系统导航返回时进行弹窗处理 首先在web-view里是不可实现的(据我了解下来) 参考小程序文档:page-container 大致逻辑: 1、page-container可实现页面离开前拦截 2、由于web-vie…

设计模式25——中介者模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。 中介者模式(Mediat…

Java基础 Day25

一、线程通信 1、简介 确保线程能够按照预定的顺序执行并且能够安全地访问共享资源 使多条线程更好的进行协同工作 2、常用方法 void wait() 使当前线程进入等待状态 void notify(); 随机唤醒单个等待的线程(可以空唤醒) void notifyAll(); 唤醒…

WebSocket与实时对话式AI服务的集成

WebSocket与实时对话式AI服务的集成 在现代对话式AI系统中,传统的HTTP请求-响应模型已难以满足实时交互的体验需求。特别是用户对响应速度、逐字输出、会话上下文保持等方面提出更高要求时,需要一种能够建立持久连接并支持双向通信的协议。WebSocket正是在这一背景下,成为A…

iOS 集成网易云信IM

云信官方文档在这 看官方文档的时候&#xff0c;版本选择最新的V10。 1、CocoPods集成 pod NIMSDK_LITE 2、AppDelegate.m添加头文件 #import <NIMSDK/NIMSDK.h> 3、初始化 NIMSDKOption *mrnn_option [NIMSDKOption optionWithAppKey:"6f6568e354026d2d658a…

人工智能100问☞第37问:什么是扩散模型?

目录 ​​一、通俗解释 二、专业解析​​ 三、权威参考 扩散模型是一种​​通过系统性地添加再去除噪声来生成新数据(如图像)的生成式AI技术​​,其核心机制分为两个阶段:正向扩散​​:对原始数据(如清晰图片)逐步添加噪声,直至完全变成随机噪点(类似老照片逐渐模糊…

传输层核心技术解析

目录 一、端口号机制 二、网络诊断工具 1. netstat命令 2. pidof工具 三、UDP协议详解 协议特征 典型应用场景 四、TCP协议深度解析 核心机制 状态转换模型 特殊状态说明 五、协议对比分析 六、开发实践要点 一、端口号机制 核心作用&#xff1a;标识主机唯一进程…

IO Vs NIO

一、IO(传统阻塞式) 全称‌&#xff1a;Input/Output(输入/输出) 定义‌&#xff1a;Java 1.0 引入的基础 I/O 模型&#xff0c;基于流&#xff08;Stream&#xff09;的同步阻塞操作&#xff0c;线程在读写数据时会阻塞直到操作完成。 二、NIO(新式非阻塞式) ‌全…

基于原生JavaScript前端和 Flask 后端的Todo 应用

Demo地址&#xff1a;https://gitcode.com/rmbnetlife/todo-app-js-flask.git Python Todo 应用 这是一个使用Python Flask框架开发的简单待办事项(Todo)应用&#xff0c;采用前后端分离架构。本项目实现了待办事项的添加、删除、状态切换等基本功能&#xff0c;并提供了直观…

005 ElasticSearch 许可证过期问题

ElasticSearch 许可证过期问题 项目启动报错 org.elasticsearch.client.ResponseException: method [GET], host [http://127.0.0.1:9200], URI [/_cluster/health/], status line [HTTP/1.1 403 Forbidden] {"error":{"root_cause":[{"type":…

哪些岗位最易被AI替代?

随着AI技术高速演进&#xff0c;一场“职场大洗牌”正悄然上演。当ChatGPT出口成章、机器人能精准执勤&#xff0c;AI时代的“就业焦虑”已不再是空谈。你是否认真思考过&#xff0c;自己所处的岗位是否也正面临被AI边缘化的风险&#xff1f; 以下几类职业&#xff0c;已成为AI…

信号槽中 sender() 的作用

好的,sender() 是 Qt 框架中的一个重要函数,它用于获取触发当前槽函数的对象。在 Qt 的信号和槽机制中,一个信号可以连接到多个槽函数,而一个槽函数也可以被多个信号触发。sender() 函数允许你在槽函数中确定是哪个对象触发了当前信号。 信号和槽机制 在 Qt 中,信号和槽…

深度学习|pytorch基本运算

【1】引言 pytorch是深度学习常用的包&#xff0c;顾名思义&#xff0c;就是python适用的torch包&#xff0c;在python里面使用时直接import torch就可以调用。 需要注意的是&#xff0c;pytorch包与电脑配置、python版本有很大关系&#xff0c;一定要仔细阅读安装要求、找到…