数值的整数次方
Q:实现函数double Power(double base, int exponent),求base的exponent次方。不需要考虑溢出。
A:这是一道很简单的题,但是考虑全面和优化代码却不是那么容易,一开始乍一看可能就写出这样的代码
double Power(double base,int exponent) { double result=1.0; for(int i=0;i<exponent;++i) result*=base; return result; }
这样的代码只能给人以不严谨的感觉,因为考虑并不全面。因为exponent是一个整数,所以可能为正也有可能为负,同时base也有可能为0,我们要全面考虑才行。改进后的代码如下
double Power(double base,int exponent) { //不合法输入,对于这种输入直接输出0 if(isZero(base) && exponent<0) return 0.0; unsigned int unsignedexp=static_cast<unsigned int>(exponent); if(exponent<0) unsignedexp=static_cast<unsigned int>(-exponent); double result=PowerWithUnsignedExponent(base,unsignedexp); if(exponent<0) result=1.0/result; return result; }
double PowerWithUnsignedExponent(double base,unsigned int exponent) { double result=1.0; for(int i=0;i<exponent;++i) result*=base; return result; }
改进后的算法考虑了不合法的输入,同时也考虑了指数为负数的情况,考虑情况已经全面。但是还是有改进的空间。
我们可以将指数拆分成2的各次幂的加法,然后利用c^(a+b)=c^a*c^b,则可以有效减少乘法的次数。
double PowerWithUnsignedExponent(double base,unsigned int exponent) { std::bitset<32> bits(exponent); if(bits.none()) return 1.0; int num=bits.count(); double mutiplication[32]; for(int i=0;i<32;++i) multiplication[i]=1.0; int count=0; double power=1.0; for(int i=0;i<32 && count <num;++i) { if(i==0) power=base; else power=power*power; if(bits.at(i)) { multiplication[i]=power; ++count; } } power=1.0; for(int i=0;i<32;++i) if(bits.at(i)) power*=multiplication[i]; return power; }
我们用递归的思路进行考虑,可以得出公式
则递归的算法为
double PowerWithUnsignedExponent(double base,unsigned int exponent) { if(exponent==0) return 1.0; if(exponent==1) return base; double result=PowerWithUnsignedExponent(base,exponent/2); result*=result; if(exponent & 0x1==1) result*=base; return result; }
参考自:http://zhedahht.blog.163.com/blog/static/254111742009101563242535/