问题提出
/**
* 求 a的b次方
*/
private static double pow1(int a, int b) {
int result = 1;
while (b != 0) {
// if (b%2==1){
// result = result * a;
// a = a* a;
// b/=2;
// } else {
// a = a* a;
// b/=2;
// }
//以上if可以简写
if(b % 2 == 1) {
result = result * a;
}
a = a* a;
b/=2;
}
return result;
}
/**
* 支持负数
*/
private static double pow2(double a,double b) {
double result = 1;
if(b == 0) {
return 1;
}
if(b == 1) {
return 1;
}
if(b > 1) {
result = getResult(a, b, result); //alt + command + m
} else{
a = 1/a;
b = Math.abs(b);
result = getResult(a, b, result);
}
return result;
}
private static double getResult(double a, double b, double result) {
while(b != 0) {
if(b % 2 == 1) {
result = result * a;
}
a *= a;
b /=2;
}
return result;
}
总结:
当指数为偶数时:指数 / 2 , 底数平方
当指数为奇数时: 先将result 乘以 底数 再将底数平方,指数整除2
进阶
计算a的b次方 mod c的值 利用快速幂
公式推导:
(a·b) % p = [(a%p)·(b%p) % p]
证明:
设:
a=k1 · p + q1
b=k2 · p + q2
(a · b) = (xxxxx) p + q1·q2
(a · b) % p = (q1 · q2) % p
因为 a%p = q1 b%p = q2
所以:(a·b) % p = [(a%p)·(b%p) % p]
作用: 暴力求a的b次方 是一个一个的a相乘最终再取模
那么现在使用公式就是 每做一次乘法就取模。解决a过大 导致超出取值范围
/**
* 求 a的b次方 mod c 快速幂
*/
private static double pow1(int a, int b, int c) {
int result = 1;
//而外:防止a输入的值过大 可以先将a对c取mod
a = a%c;
while (b != 0) {
if (b % 2 == 1) { //b&1 用位运算更快
result = (result * a) % c; //每一步乘法进行取模运算
}
a = (a * a) % c;
b /= 2; //b>>1 运算更快
}
return result;
}