《数据结构与算法分析-C语言描述》详解-Sec2(三)幂指数运算

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013810296/article/details/67639741

编写程序计算整数X的N次方,这个问题一个难点在于如何减少运算复杂度

遍历自乘法

//输出X的N次方,连续自乘
//O(N)
long int Power(int X, unsigned int N)
{
    unsigned long temp = 1;
    for (int i = 0; i < N; i++)
        temp = temp * X;
    return temp;
}

这个算法依次进行N次对X的乘法,运算复杂度为O(N),这是最直接简单的方法,但这个算法是可以提高的,如日常中计算64,我们下意识都会用8*8而不是将两个8分别各计算出来再相乘

因此简单的遍历相乘这个算法中隐含了重复性的计算

对分法

//若M为偶数输出true,为奇数输出false
bool IsEven(unsigned int M)
{
    //return (M % 2 == 0 ) ? true : false;
    return ((M & 0x01) == 0) ? true : false;
}

//递归计算X的N次方
//O(logN)
long int Pow_rec( int X, unsigned int N)
{
    if (N == 0)
        return 1;
    if (IsEven(N))
        return Pow_rec(X*X, N / 2);
    else
        return Pow_rec(X*X, N / 2)*X;
}

这个算法中使用递归方法,每次递归中判断指数N的奇偶性,如果为偶数则计算 XN/2XN/2 ,否则计算 XN/2XN/2X ,这样每次都将指数的规模减小一半,每次递归中进行1次或2次乘法,一共进行log(N)次递归,因此运算复杂度为O(log(N)),以计算 233 为例:

T N return
1 33 2162162 = (22)162
2 16 2828 = (22)8
3 8 2424 = (22)4
4 4 2222 = (22)2
5 2 2121 = (22)1
6 1 2020 = (22)0

容易得到一共进行了6次递归,递归次数等于 log(223)+1 的取整。

上述程序中要求底数X为整数,指数N为正整数,只覆盖了幂运算的一小部分,实际中需要考虑的情况有:

  • 指数N为负整数
//递归计算X的N次方,考虑N为负整数
//O(logN)
double Powe_rec_neg(int X, int N)
{
    if (N < 0 && X == 0)
        return 0;
    if (N < 0)
        return -(1.0 / (double)Pow_rec(X, (unsigned int)-N));
    return Pow_rec(X, N);
}
  • 底数X为浮点型实数

修改类型即可,但需要注意在判断底数X==0和指数N<0同时满足的情况时,由于此时X为浮点型,因此不能直接使用==,而应该单独判断:

bool equal(double elem1, double elem2)  
{  
    if ((elem1 - elem2 < 0.0000001) && (elem1 - elem2 > -0.0000001))  
        return true;   //相等  
    else  
        return false;   //不相等  
}  
  • 指数N为小数

指数为小数或者分数时,实际上是开方运算,与简单的幂运算已经完全不同了,这部分需要另外单独进行讨论

同时受限于long int长度,算法中只能计算小于 232 次方的幂,如何对于大数进行幂运算则是另外一个并不简单的问题

猜你喜欢

转载自blog.csdn.net/u013810296/article/details/67639741