Pow(x, n) 求一个数的n次方

我们知道C++中是有pow函数的,我们这次自己来写个,因为有这样的算法题目。

所需数学知识:

大致考虑正数,0,负数即可。n多个数相乘的问题。

 

1.简单For循环

 

这还不简单,马上写一个for循环:

double pow(double x, int n){
	int m = abs(n);
	double result = 1;
	for(int i = 0; i < m; ++i){
		result *= x;
	}
	return n > 0 ? result : 1/result;
}

 

2.最慢的递归求解

 

受 1+2+3+4+5…+N的问题用递归求解思路影响,我们知道这里可以用一个非常慢的递归来求解。

 

double pow(double x, int n){
    if(n == 0){
        return 1;
    }
    if(n > 0 ){
          return x * pow(x, n - 1);
     }else{
          return 1 /  pow(x, -n);
     }

}

搞不好比for循环还要慢。

 

3.很大改进的递归求解

 

 

都先考虑正数。我们在想,n多个2相乘,如果n刚好能被2整除,我们可以把n分成一半一半来考虑。

可以把它们想成是一半*一半,不能被2整除的话,也只是多乘以一个自己。

double pow(double x, int n){
	if(n == 0){
		return 1;
	}
        if(n > 0 ){
	    double half = pow(x, n / 2);
	    if(n % 2 == 0){
		return half * half;
	    }else{
		return half * half * x;
	    }			
	}else{
		return 1 /  pow(x, -n);
	}
}

我们知道这里的 n / 2,和 n % 2还可以用位运算来提高速度

n / 2  ==  n >> 1 (在返回是int值的情况下)

n % 2 == n&1

修改如下:

 

double pow(double x, int n){
	if(n == 0){
		return 1;
	}
        if(n > 0 ){
	    double half = pow(x, n >> 1);
	    if((n&1) == 0){
		return half * half;
	    }else{
		return half * half * x;
	    }			
	}else{
		return 1 /  pow(x, -n);
	}
}

 

4.当然还有优化空间!

3标题中我们其实做的事情是对n的每次取半再相加,这样太慢了,直接除以2比较快。当然遇到不能整除的要多乘以一个自己。

 

double pow(double x, int n){
	int m = abs(n);
	double result = 1;
	while(m > 0){
		if(m % 2 != 0){
			result = result * x;
		}
		x *= x;
		m = m / 2;
	}
	return n > 0 ? result : 1 / result;
}

通过位运算优化后就是:

 

 

double myPowFunction(double x, int n){
    int m = abs(n);
    double result = 1;
    while(m > 0){
        if((m&1) != 0){
            result = result * x;
        }
        x *= x;
        m >>= 1;
    }
    return n > 0 ? result : 1 / result;
}

看了下vs中的pow实现,也是类似的思想。

 http://www.waitingfy.com/archives/998

Tags:

998

Leave a Reply

Name and Email Address are required fields.
Your email will not be published or shared with third parties.