每日算法快速幂
Posted jiange_zh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日算法快速幂相关的知识,希望对你有一定的参考价值。
数值的整数次方
实现函数
double Power(double base, int n)
求base的n次方,不得使用库函数,同时不需要考虑大数问题。
Tips
问题本身很直观,但是越简单的题越需要细心思考,包括边界问题和效率问题,如果不能考虑到以下3点,就无法给出令人满意的答案:
- 考虑n为负数的情况;
- 考虑base为0的情况;
- 当n较大时,如何保证效率?
分析
针对上面3个问题,我们逐一解答:
1.在计算的时候,我们统一计算base的 abs(n)次方,最后如果是负数,答案应该取倒数;
2.如果base为0,则它不能做分母,此时若n<0,则我们应该返回错误信息。
关于返回错误信息,一般有以下方法:
- 通过返回值;
- 通过全局变量;
- 抛出异常;
在这里,我们注意到返回值本身可以取任意值,所以不能单纯靠返回值;如果仅设置全局变量,那么每次计算之后都有检查,比较麻烦;我们可以选择返回值+全局变量的形式来返回错误:
如果有错,返回0,且设置全局变量。
3.当n较大时,可使用快速幂:
若n为偶数, base^n = base^(n/2) * base^(n/2);
若n为奇数, base^n = base * base^((n-1)/2) * base^((n-1)/2);
解答
下面是Power函数:
bool error = false;
double Power(double base, int n)
{
error = false;
if (equal(base, 0.0) && n < 0)
{
error = true;
return 0.0;
}
unsigned int absN = (unsigned int)n;
if (n < 0)
absN = (unsigned int)(-n);
double result = PowerWithUnsignedN(base, absN);
if (n < 0)
result = 1.0/result;
return result;
}
Notice:对于小数,判断是否相等不能直接用 == ,而应该计算两者的差值在一个精度范围内:
bool equal(int num1, int num2)
{
if ((num1-num2) > -0.0000001 && (num1-num2) < 0.0000001)
return true;
else
return false;
}
下面是核心的快速幂的递归版本:
double PowerWithUnsignedN(double base, unsigned int n)
{
if (0 == n) return 1;
if (1 == n) return base;
double res = PowerWithUnsignedN(base, n>>1);
res *= res;
if (n & 1) //n为奇数
res *= base;
return res;
}
一般情况下,以上代码已经很完美了~
不过如果你更加追求效率,想必递归版本并不能满足你,那么可以试一试下面的非递归版本:
double PowerWithUnsignedN(double base, unsigned int n)
{
double res = 1.0;
while (n > 0)
{
if (n & 1)
res *= base;
base *= base;
n >>= 1;
}
return res;
}
关于快速幂,我们常常用来做快速幂取模等,稍微复杂一点,我们可以用它来做矩阵的快速幂,原理是一样的,只是操作的对象是一个矩阵而不是一个数(矩阵快速幂以求斐波那契数列较为著名,此处暂不展开,后面会开专题写斐波那契数列,有兴趣的读者可以先自行查找相关资料)。
每天进步一点点,Come on!
(●’?’●)
本人水平有限,如文章内容有错漏之处,敬请各位读者指出,谢谢!
以上是关于每日算法快速幂的主要内容,如果未能解决你的问题,请参考以下文章