快速乘法通过处理被乘数 b b b的二进制位,将乘法运算转化为加法和位移操作来实现高效计算。以下是快速乘法的详细原理解析。
1. 乘法的二进制表示原理
(1) 二进制展开
任何整数
b
b
b都可以用二进制表示为:
b
=
b
0
⋅
2
0
+
b
1
⋅
2
1
+
b
2
⋅
2
2
+
⋯
+
b
n
⋅
2
n
b = b_0 \cdot 2^0 + b_1 \cdot 2^1 + b_2 \cdot 2^2 + \dots + b_n \cdot 2^n
b=b0⋅20+b1⋅21+b2⋅22+⋯+bn⋅2n
其中:
- b i ∈ { 0 , 1 } b_i \in \{0, 1\} bi∈{0,1}表示 b b b的第 i i i个二进制位。
- 2 i 2^i 2i是对应位的权值。
乘法
a
×
b
a \times b
a×b可以写成:
a
×
b
=
a
⋅
(
b
0
⋅
2
0
+
b
1
⋅
2
1
+
⋯
+
b
n
⋅
2
n
)
a \times b = a \cdot (b_0 \cdot 2^0 + b_1 \cdot 2^1 + \dots + b_n \cdot 2^n)
a×b=a⋅(b0⋅20+b1⋅21+⋯+bn⋅2n)
= ( a ⋅ b 0 ) ⋅ 2 0 + ( a ⋅ b 1 ) ⋅ 2 1 + ⋯ + ( a ⋅ b n ) ⋅ 2 n = (a \cdot b_0) \cdot 2^0 + (a \cdot b_1) \cdot 2^1 + \dots + (a \cdot b_n) \cdot 2^n =(a⋅b0)⋅20+(a⋅b1)⋅21+⋯+(a⋅bn)⋅2n
(2) 转换为加法与移位
-
当 b i = 1 b_i = 1 bi=1时,结果中需要加上 a ⋅ 2 i a \cdot 2^i a⋅2i。
-
当 b i = 0 b_i = 0 bi=0时,跳过当前位。
-
由于 2 i 2^i 2i的倍乘可以通过位移(左移)实现:
a ⋅ 2 i ≡ 将 a 左移 i 位 a \cdot 2^i \equiv \text{将 } a \text{ 左移 } i \text{ 位} a⋅2i≡将 a 左移 i 位
因此,可以通过逐位检查 b b b的二进制表示:
- 检查 b b b当前最低位(是否为 1)。
- 如果是 1,将当前的 a a a加入结果。
- 每次将 a a a左移 1 位(相当于乘以 2),将 b b b右移 1 位(相当于去掉最低位)。
2. 快速乘法的执行步骤
快速乘法依赖上述二进制展开,通过循环(或递归)实现如下步骤:
(1) 初始化
- 定义结果变量 result = 0 \text{result} = 0 result=0,用来累加计算结果。
- 初始 a a a保持不变, b b b表示被乘数。
(2) 循环逐位处理 b b b
- 检查最低位:
- 取 b b b的最低位 b m o d 2 b \mod 2 bmod2或 b & 1 b \& 1 b&1。
- 如果最低位为 1,说明当前 b b b的这一位需要加上对应的位权(当前的 a a a)。
- 如果最低位为 0,跳过本次计算。
- 更新结果:
- 如果最低位为 1,则累加结果: result + = a \text{result} += a result+=a。
- 位移操作:
- 将 a a a左移 1 位(相当于乘以 2),以便计算下一位的贡献。
- 将 b b b右移 1 位(相当于移除最低位),继续处理下一位。
(3) 终止条件
- 当 b = 0 b = 0 b=0时,所有位已处理完,计算结束。
3. 快速乘法原理详解示例
示例:计算 a = 13 , b = 11 a = 13, b = 11 a=13,b=11
二进制表示:
- a = 13 = 110 1 2 a = 13 = 1101_2 a=13=11012
- b = 11 = 101 1 2 b = 11 = 1011_2 b=11=10112
展开计算过程:
a
×
b
=
13
×
11
=
13
×
(
1
⋅
2
0
+
1
⋅
2
1
+
0
⋅
2
2
+
1
⋅
2
3
)
a \times b = 13 \times 11 = 13 \times (1 \cdot 2^0 + 1 \cdot 2^1 + 0 \cdot 2^2 + 1 \cdot 2^3)
a×b=13×11=13×(1⋅20+1⋅21+0⋅22+1⋅23)
= 13 × 1 + 13 × 2 + 13 × 8 = 13 \times 1 + 13 \times 2 + 13 \times 8 =13×1+13×2+13×8
逐步计算过程(用快速乘法实现)
步骤 | b b b二进制 | b b b值 | b b b当前位 | a a a值 | 累加结果 result \text{result} result | 操作 |
---|---|---|---|---|---|---|
初始 | 101 1 2 1011_2 10112 | 11 | 1 | 13 | 0 | 检查最低位,累加 13 13 13 |
第1步 | 010 1 2 0101_2 01012 | 5 | 1 | 26 ( 13 × 2 13 \times 2 13×2) | 13 | 累加 26 26 26 |
第2步 | 001 0 2 0010_2 00102 | 2 | 0 | 52 ( 26 × 2 26 \times 2 26×2) | 39 | 跳过(最低位为 0) |
第3步 | 000 1 2 0001_2 00012 | 1 | 1 | 104 ( 52 × 2 52 \times 2 52×2) | 39 | 累加 104 104 104 |
结束 | 000 0 2 0000_2 00002 | 0 | - | - | 143 | 计算完成 |
结果:
13
×
11
=
143
13 \times 11 = 143
13×11=143
4. 代码实现
迭代实现
public class FastMultiplication {
public static long multiply(long a, long b) {
long result = 0; // 初始化结果
while (b > 0) { // 当 b > 0 时循环
if ((b & 1) == 1) { // 检查 b 的最低位是否为 1
result += a; // 累加当前的 a
}
a <<= 1; // a 左移(乘以 2)
b >>= 1; // b 右移(去掉最低位)
}
return result; // 返回结果
}
public static void main(String[] args) {
System.out.println(multiply(13, 11)); // 输出 143
}
}
5. 快速乘法的复杂度分析
时间复杂度
快速乘法处理 b b b的每一位,总共需要 O ( log b ) O(\log b) O(logb)次操作:
- 每次循环包括一个加法操作和两次位移操作(左移和右移),都在常数时间内完成。
因此,时间复杂度为:
O
(
log
b
)
O(\log b)
O(logb)
空间复杂度
快速乘法只使用常数个变量
a
a
a、
b
b
b和
r
e
s
u
l
t
result
result,因此空间复杂度为:
O
(
1
)
O(1)
O(1)
6. 快速乘法的优势与局限
优势
- 效率高:
- 避免了暴力乘法需要的 O ( b ) O(b) O(b)次加法操作。
- 转化为 O ( log b ) O(\log b) O(logb)的复杂度,大幅提升性能。
- 适合硬件实现:
- 快速乘法主要使用位操作和加法,适合嵌入式硬件中的实现。
局限
- 只适合整数乘法:
- 快速乘法的核心思想依赖于整数的二进制表示,不适合小数乘法。
- 溢出问题:
- 如果结果过大,可能会导致溢出(在需要大数时需额外处理)。
7. 应用场景
- 嵌入式系统和硬件优化:
- 在低端硬件中,可能没有专用乘法指令,快速乘法可以通过位移和加法模拟乘法。
- 大数运算:
- 快速乘法可以用于高效计算超出基本数据类型范围的大数。
- 模运算中的快速乘法:
- 在加密算法(如 RSA)中,结合快速乘法和模运算避免溢出。
快速乘法是通过二进制分解和位操作优化乘法运算的高效算法。它利用二进制的逐位处理特性,大幅减少了计算量,尤其适用于整数运算和大数场景。