函数介绍:接受两个整数参数
a
和b
,并返回 (a^b) 的结果
public static int quickpow(int a, int b) {
int ans = 1;
while (b > 0) {
if ((b & 1) == 1) {
ans *= a;
}
a *= a;
b >>= 1;
}
return ans;
}
变量初始化
int ans = 1 ;
这里 ans
初始化为1,因为在幂运算中,任何数的0次方都是1。
判断指数的奇偶性
if ((b & 1) == 1) {
ans *= a;
}
在快速幂算法中,判断指数的奇偶性是关键步骤,因为算法依赖于二进制表示来减少乘法次数。如果指数 b
是奇数,那么在计算 a^b
时,当前的底数 a
必须被乘入结果 ans
中。如果 b
是偶数,则当前的 a
不需要直接乘入 ans
,因为 a
的平方将在后续的迭代中计算。
在二进制表示中,一个数的最低位(即最右边的位)决定了这个数是奇数还是偶数。如果该位是1,则这个数是奇数;如果该位是0,则这个数是偶数。位运算 b & 1
就是用来检查 b
的最低位是否为1的。
因此,在快速幂算法中,判断奇偶性的目的是确定在当前迭代中是否需要将 a
乘入 ans
。这是算法正确性的关键部分,因为它确保了只有在需要时才进行乘法运算,从而减少了总的乘法次数。
举例来说,假设我们要计算 a^13
。在二进制中,13
表示为 1101
。快速幂算法会按如下方式计算:
b = 13
,ans = 1
,a
保持不变b
是奇数 (13 & 1 = 1
),所以ans *= a
(此时ans = a
)a
自乘:a *= a
(此时a = a^2
)b
右移一位:b >>= 1
(此时b = 6
)b
是偶数 (6 & 1 = 0
),所以ans
不变a
自乘:a *= a
(此时a = a^4
)b
右移一位:b >>= 1
(此时b = 3
)b
是奇数 (3 & 1 = 1
),所以ans *= a
(此时ans = a^5
)a
自乘:a *= a
(此时a = a^8
)b
右移一位:b >>= 1
(此时b = 1
)b
是奇数 (1 & 1 = 1
),所以ans *= a
(此时ans = a^13
)- 算法结束,返回
ans
通过判断奇偶性,我们可以确保只在需要时才进行乘法运算,从而优化算法的性能。如果忽略了这一步,那么每次迭代都会进行乘法运算,这将导致算法退化为简单的幂运算,失去了快速幂算法的优势。
使用位运算来判断 b
的最低位是否为1(即判断 b
是否为奇数)。如果 b
是奇数,那么我们需要将当前的 a
值乘到 ans
上。
平方底数
a *= a;
无论 b
是奇数还是偶数,我们都需要将 a
自乘,以便在下一次迭代中使用它的平方值。
指数右移
b >>= 1;
将 b
右移一位,相当于将 b
除以2。这是因为我们在每一次循环中已经处理了 b
的最低位。
TIPS:这个版本的函数没有考虑整数溢出的问题。在实际应用中,如果 a
和 b
非常大,可能会导致 ans
的值溢出 int
类型的范围。如果需要处理大整数幂运算,可能需要使用 BigInteger
类或其他方法来避免溢出问题。