前提知识:
十进制与二进制相互转换
n&1 (与操作): 判断 n 二进制最右一位是否为 1如为1则返回真
n>>1 (移位操作): n 右移一位(可理解为删除最后一位,n除以2)
快速乘法模板:
无论是快速乘法a∗ba*ba∗b还是快速幂 aba^{b}ab ,对其进行二进制拆分,把b拆成二进制形式。
a∗b=a∗(a*b=a*(a∗b=a∗(ck-1∗2k−1+*2^{k-1}+∗2k−1+ck-2∗2k−2+*2^{k-2}+∗2k−2+ck-3∗2k−3+*2^{k-3}+∗2k−3+…+++c0∗20*2^{0}∗20)其中c就是二进制位是否为1
例如:3*9
9转换成二进制为1001,那么原式= 3∗9=3∗(3*9=3*(3∗9=3∗( 1∗23+*2^{3}+∗23+ 0∗22+*2^{2}+∗22+ 0∗21+*2^{1}+∗21+…+++ 1∗20*2^{0}∗20)
代码如下:
@Override
static long mul(long a, long k) {
//返回的结果
long ans = 0;
while (k > 0) {
//判断二进制的那一位是否为1,若为1则+不为1则跳过
if ((k & 1) == 1) ans += a;
//右移操作
k >>= 1;
//a自加相当于乘以2
a += a;
}
return ans;
}
快速幂:
无论是快速乘法a∗ba*ba∗b还是快速幂 aba^{b}ab ,对其进行二进制拆分,把b拆成二进制形式。
ab=a^{b}=ab= a^(ck-1∗2k−1+*2^{k-1}+∗2k−1+ck-2∗2k−2+*2^{k-2}+∗2k−2+ck-3∗2k−3+*2^{k-3}+∗2k−3+…+++c0∗20*2^{0}∗20)其中c就是二进制位是否为1,于快速乘在代码中有所区别的地方在于将加法变成了乘法。
@Override
static double myPow(double x, int n) {
if(x == 0.0f) return 0.0d;
long b = n;
double ans = 1.0;
//判断n是否小于0,小于0转换成分数
if (b < 0){
x = 1/x;
b = -b;
}
while(b >0){
if((b&1)==1) ans*=x;
b=b>>1;
x*=x;
}
return ans;
}
本文介绍了从二进制角度理解快速乘法和快速幂的方法,讲解了如何利用二进制拆分进行高效计算。通过十进制与二进制转换,结合位操作,详细阐述了快速乘法的模板,并以3*9为例进行演示。同时,对比快速乘法,快速幂将加法转换为乘法,进一步优化了计算过程。
3193

被折叠的 条评论
为什么被折叠?



