让x升到第n个力量

时间:2012-06-29 03:35:24

标签: c performance time-complexity runtime-compilation

我是新手,我知道我在互联网上获得的这个C程序(学分:http://www.geeksforgeeks.org/archives/28)可以正常工作。

#include<stdio.h>

float power(float x, int y)
{
    float temp;
    if( y == 0)
       return 1;
    temp = power(x, y/2);
    if (y%2 == 0)
        return temp*temp;
    else
    {
        if(y > 0)
            return x*temp*temp;
        else
            return (temp*temp)/x;
    }
}

/* Program to test function power */
int main()
{
    float x=2;
    int y=5;
    printf("%f", power(x, y));
    getchar();
    return 0;
}


我只是想知道如何以及为什么。我在这个函数中的代码行之后发表了我的问题/评论......

float temp;
if( y == 0)
   return 1; 
       //this I understand because for instance 2^0 is 1
temp = power(x, y/2);
if (y%2 == 0)
    return temp*temp; 
        //if y is even, eg. 2^4 then 2^2 * 2^2 is still equal to 16
else
{
    if(y > 0) 
        //this part I don't get anymore. eg. 2^5, then temp=2^(5/2)
        return x*temp*temp; 
            //2 * 2^(5/2) * 2^(5/2) how? this will become 64 but the answer is 32.
            //but when I run the program it halts the right answer ie, 32
    else
        return (temp*temp)/x;
}


请向我解释发生了什么。也许我只是错过了什么。以及它如何成为 O(lg n)的运行时间。非常感谢你!

5 个答案:

答案 0 :(得分:4)

请注意,用于计算temp的y/2整数除法。所以在你评论的问题中,5/2的结果将是2,而不是2.5。

答案 1 :(得分:3)

很难与维基百科对exponentiation by squaring的解释竞争,但这是我的看法。

答案的关键在于这个公式:

a^(b*c) == ((a^b)^c)

这会立即回答“权力均衡时该怎么办”的问题:如果y=2*k,则可以先对x进行平方,然后将结果提升为{{1}的幂}。

奇数功率的情况有点复杂:让我们重写

k

as

x ^ (2*k+1)

现在你看到(x ^ 2*k) * x 分支发生了什么:他们从奇数中减去一个,使其变为偶数,得到else,最后乘以x ^ (y-1) *

现在考虑时间复杂度:每一步都将x减少一半,因此递归调用的次数为y

<小时/> * 该实现不会明确地从O(Log2(N))中减去1。相反,它执行y的整数除法,它会丢弃除法的其余部分。

答案 2 :(得分:0)

/* if y is even and positive, e.g., 5, then floor of y/2 is (y-1)/2, e.g. 4/2
   then x^((y-1)/2 + (y-1)/2 + 1) = x^y, e.g., x * x^2 * x^2 = x^(1+2+2) = x^5) */
if(y > 0) 
    return x*temp*temp; 

/* if y is even and negative, e.g., -5, then floor of y/2 is (y+1)/2, e.g. -4/2
   then x^((y+1)/2 - (y+1)/2 - 1) = x^y, e.g., x^-1 * x^-2 * x^-2 = x^(-1-2-2) = x^-5) */

else
    return (temp*temp)/x;

至于复杂度O(lgn),因为在每次递归功率调用之前你除以2,你最多会进行lg(n)次调用。

答案 3 :(得分:0)

这是通常的x n 算法的有点笨重的实现,它在将n减半时重复x方格。奇数n需要额外处理:在每一步中,检查n是否为奇数,并乘以另一个因子。

Alexander Stepanov's 1 非常好lecture series on generic/templated algorithms解释了这个问题的起源:

来自古埃及算法的乘法重复加法,同时将n减半。

第一堂课的开头很简单,但很好。他有趣的旁边和故事。他从一个递归的算法开始,通过重复加法进行乘法运算,并以各种方式对其进行精炼。他到了replacing + with * to make this exponentiation algo near the end of lecture 2 (of 4)

1:Stepanov设计并实现了很多C ++的STL。他是通用编程的早期发明者/先驱之一。我很喜欢他的讲座,并会推荐他们。

这个特殊的实现对我来说并不好看。

我还没想过,但肯定有更好的方法来处理负奇n而非分裂。这可能是C&C整数除法的舍入方向的怪癖? (它与算术右移不同,即使在C实现上,对于带符号的操作数上的>>进行算术移位也是如此.C标准并不要求这样做,但是在某些特定情况下C实现它确实有定义的行为。)

此外,变量名称具有误导性:通常您希望yx具有相同的类型。如果要混合整数和FP变量,请使用n之类的名称作为整数。

答案 4 :(得分:-1)

private int nthPower(int num, int power)
    {
        int [] arr = new int[power+1];
        arr[0] = 1; // Any number to the power '0' is '1'
        arr[1] = num; // Any number to the power '1' is num itself.
        int i =2;
        //Now in the for loop you just fill the next element in the array 
        // by multiplying the num with its previous result. Once you are out 
        // of loop you have the desired answer in 'i-1' th index.
        for (i =2; i<=power;i++)
        {
            arr[i] = num*arr[i-1];
        }
        return arr[i-1]; //This is your answer
    }