当前位置: 首页 > news >正文

✨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.xdnf.cn/news/736435.html

相关文章:

  • 在 Android 上备份短信:保护您的对话
  • N2语法 状態
  • win7怎么关闭开机自启动程序?
  • 深入理解 MySQL 隔离级别:理论与实战
  • 百年陈韵,三代匠心——陈汇堂新会陈皮的传承与新生
  • linux 中路由解决方案1
  • Cross-Encoder(交叉编码器)和 Bi-Encoder(双编码器)
  • 页面表格、模型、脚本这三者之间的数据是如何传输的?尤其是模型(Model)到底是怎样的运作原理与数据流转?
  • 判断质数的基础方法
  • Maven高级篇
  • Selenium操作指南(全)
  • 本地部署AI工作流
  • vivado仿真文件的相对地址设置方法
  • LangChain第二页_【教程】翻译完了
  • 前端面试之Proxy与Reflect
  • tryhackme——Windows Internals
  • PyQt6基础_QtCharts绘制横向柱状图
  • 代码随想录算法训练营第60期第五十二天打卡
  • 六步完成软件验收:从计划到终验的全面指南(一)
  • 【瑶池数据库训练营及解决方案本周精选(探索PolarDB,参与RDS迁移、连接训练营)】
  • mobile app 工具简要对比
  • 秒出PPT正式改名秒出AI,开启AI赋能新体验!
  • 数字人革新教育:开启智慧教学新时代
  • 力扣面试150题--二叉树的层平均值
  • 探讨分贝计在医疗环境中的具体应用及其重要性
  • 基于VU37P的高性能采集板卡
  • (独家)SAP VC物料 超级BOM怎么开单?怎么计算或发布表标准成本?
  • 第10讲、Odoo 18框架设计原理全解析
  • Redis 难懂命令-- ZINTERSTORE
  • mysql怎么查询longblob类型数据的大小