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

算法与数据结构:位运算与快速幂

文章目录

        • 位运算
        • 快速幂

位运算

在计算机的世界中,一切数字都是二进制的。类比于现实世界中我们所使用的十进制,二进制即为「逢二进一」的运算体系。

我们以 B、D 来分别标记二进制与十进制,例如 10D 表示十进制中的 10,而 10B 则表示二进制中的 10。

回顾十进制,
10 D = 1 × 1 0 1 + 0 × 1 0 0 = 10 123 D = 1 × 1 0 2 + 2 × 1 0 1 + 3 × 1 0 0 = 123 10D = 1\times 10^1 + 0\times 10^0 = 10 \\ 123D = 1\times 10^2 + 2\times 10^1 + 3\times 10^0 = 123 10D=1×101+0×100=10123D=1×102+2×101+3×100=123

类比十进制,进一步理解二进制:
10 B = 1 × 2 1 + 0 × 2 0 = 2 D 123 B = 1 × 2 2 + 2 × 2 1 + 3 × 2 0 = 11 D 10B = 1\times 2^1 + 0\times 2^0 = 2D\\ 123B = 1\times 2^2 + 2\times 2^1 + 3\times 2^0 = 11D 10B=1×21+0×20=2D123B=1×22+2×21+3×20=11D

由此我们可以发现,十进制就是「逢十进一」,而二进制就是「逢二进一」。

在计算机的运算过程中,所有的数字都是用「二进制」表示的,其中数字的每一位称为一个 bit,其取值要么为 0,要么为 1

「位运算」是「二进制」所特有的运算,共分为 6 类,如下表所示:

运算符名称规则
&两个位均为1,结果为1
|两个位均为0,结果为0
^异或两个位相同则为0,不同则为1
~取反0变1,1变0
<<左移二进制下所有位同时向左移动,低位用0填充,高位越界后舍弃
>>右移二进制下所有位同时向右移动,无符号数高位补0,有符号数视编译器而定

我们以 1011B、0101B 举例(均为无符号数):

  • 1011B & 0101B = 0001B
  • 1011B | 0101B = 1111B
  • 1011B ^ 0101B = 1110B
  • ~1011B = 0100B
  • 1011B << 2 = 101100B
  • 1011B >> 2 = 10B

想要彻底掌握位运算,还需了解原码、反码、补码等知识,但由于本文重点并不在此,因此不再详细展开。

快速幂

接下来开始介绍「快速幂」算法,该算法常用于快速指数运算。

举个例子,如果想要计算 2 31 2^{31} 231 的具体数值,最少需要计算多少次可以完成?

一个比较显然的答案是从 1 开始连乘 31 个 2,这样肯定可以得到准确的答案,但是否有更快的方法?

答案显然是「有」,如果我们用二进制来表示 31,则可以得到:
31 D = 11111 B = 1 × 2 4 + 1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0 = 31 D 31D = 11111B = 1\times 2^4 + 1\times 2^3 + 1\times 2^2 + 1\times 2^1 + 1\times 2^0 = 31D 31D=11111B=1×24+1×23+1×22+1×21+1×20=31D

由此我们可以将 2 31 2^{31} 231 进行转化,得到:
2 31 = 2 1 + 2 + 4 + 8 + 16 = 2 1 × 2 2 × 2 4 × 2 8 × 2 16 2^{31} = 2^{1+2+4+8+16} = 2^1\times 2^2\times 2^4 \times 2^8 \times 2^{16} 231=21+2+4+8+16=21×22×24×28×216

因此我们只需要求出 2 1 , 2 2 , 2 4 , 2 8 , 2 16 2^1, 2^2, 2^4, 2^8 , 2^{16} 21,22,24,28,216 ,再将它们依次相乘,就可以得到 2 31 2^{31} 231

我们从 1 开始只需要计算 5 次即可求出 2 16 2^{16} 216 。再将这几个数字依次乘起来,就得到了 2 31 2^{31} 231

这种通过将指数转化为二进制,并以此来加快幂运算的方法就是快速幂。当计算
a x a^x ax ( a 为任意实数)时,快速幂方法可以将原来的 O ( x ) O(x) O(x) 时间复杂度降低为
O ( l o g ( x ) ) O(log(x)) O(log(x)) ,从而大大加快指数运算。

实现该算法所需代码并不长,大家可以手动实现,也可以参考下述代码:

// 计算 a ^ b
int poww (int a, int b) {int base = a, ans = 1;while (b) {if (b & 1) ans *= base;base *= base;b >>= 1;}return ans;
}
# 快速幂算法
def poww(a, b):base = a;ans = 1;while (b):print("b:", b)if ( b & 1):ans *= base;base *= base;b >>= 1;print(ans);return ans;poww(2, 14);b: 14
b: 7
b: 3
b: 1
16384
http://www.xdnf.cn/news/546931.html

相关文章:

  • 地理信息数据格式.GeoJSON数据格式介绍
  • 无人机避障——深蓝学院浙大Fast-planner学习部分(采用均匀B-Spline和非均匀B-Spline进行轨迹优化和时间重分配)
  • 力扣-盛最多水的容器
  • 网络刷卡器的分类和网口通讯流程
  • hghac集群服务器时间同步(chrony同步)
  • 替换word中的excel
  • 【25软考网工】第七章 (2)UOS Linux文件和目录管理、用户和组管理
  • 音频应用的MediaSession冲突
  • Transfomer学习
  • Java NIO(New I/O)
  • ubuntu kubeasz 部署高可用k8s 集群
  • k8s1.27版本集群部署minio分布式
  • 01 基本介绍及Pod基础
  • 【DCGMI专题1】---DCGMI 在 Ubuntu 22.04 上的深度安装指南与原理分析(含架构图解)
  • 深度学习架构快速入门——卷积神经网络CNN、循环神经网络RNN、生成对抗网络GAN、Transformer以及编码器-解码器
  • Jenkins:自动化之魂,解锁高效开发的密钥
  • 2025-05-20 模型下载--文本向量化--Faiss检索
  • SQLMesh 内置宏详解:@PIVOT等常用宏的核心用法与示例
  • Qt文件:XML文件
  • 战略游戏--树形dp
  • Java中字符串(String类)的常用方法
  • 如何使用MATLAB NLP工具箱进行文本聚类
  • notepad++
  • 使用 vite-plugin-dynamic-base 实现运行时动态设置上下文路径
  • SetThrowSegvLongjmpSEHFilter错误和myFuncInitialize 崩溃
  • 深度学习框架显存泄漏诊断手册(基于PyTorch的Memory Snapshot对比分析方法)
  • LLM: 多模态LLM动态分辨率
  • AI知识库- Cherry Studio构建本地知识库
  • winrm ‘Protocol‘ object has no attribute ‘run_ps‘
  • AI编程辅助哪家强?深度解析主流AI编程工具的现状与未来-优雅草卓伊凡