《剑指offer》:[15]实现指数函数:x的y次方

“最不能容忍的功能错误,忽略边界情况。必须保证功能测试、边界测试、负面测试以及性能测试”          

                                                                                                                       ------尹彦(Intel)

问题:数值的整数次方
实现double(double base,int exponent),求base的exponent次方。不得使用库函数,不需要考虑大数问题。
这个题不需要考虑大数的问题就让问题简化了很多。如果考虑大数还得申请数组装大数。
一般看到这样的题目我们很快就会写出其代码:
double Power(double base,int exponent)
{
   double result=0.0;
   for(int i=0;i<exponent;i++)
      result*=base;
   return result;
}
  很多人看见题目都能想到这儿,于是随手写下了这段代码。对于一般的整数的次方确实可以解决,但是这能远观不能近看。细细一品,漏洞百出啊!
问题大集合,从边界和负面测试来考虑:
问题一:如果base为负这个程序就傻了。所以先的对输入的数据进行判断,看是否有效。
问题二:如果指数为负这个程序又傻了。我们的先求绝对值,然后算出次方的结果之后再取导数。
问题三:就算考虑了问题一,但是如果指数为base为0,那么该程序还是傻了。我们在求导数的时候一定要考虑分母为0的情况,否则程序只能用down来回报我们了。
问题四:如果输入0的0次方,这个在数学上虽然没有意义,但是计算机它不知道,它又傻了。如果返回我们想返回的值0,我们一定要记得去判断0这个值是出错后的0,还是正常返回的0;
问题五:double 类型的base怎么和0比较,难道是base==0?这样计算机又要跟你开玩笑了!所以还得写定义一个equal函数:abs(number1-number2)<0.0000001--来判断是否为0。
以上五个因素的任意一个出现都会使我们的程序出错或者down掉,快不一定是好事儿。所以考虑要全面:
考虑后,具体实现代码如下:
#include <iostream>
#include <math.h>
using namespace std;
bool InvalidInput=false;
double PowerwihtUnsignedExponent(double base,unsigned int exponent)
{
	double result=1.0;
	for( unsigned int i=0;i<exponent;i++)
		result*=base;
	return result;
}
bool equals(double num1,double num2)
{
	if(fabs(num1-num2)<0.0000001)
		return true;
	else
		return false;
}
double Power(double base,int exponent)
{
	InvalidInput=false;
	if(equals(base,0.0) || base<0 )  //base为<=0;
	{
		InvalidInput=true;
		cout<<"INVALID INPUT"<<endl;
		return 0.0;
	}
	if(0==exponent)  //base^0次方;
	{
		return 1.0;
	}
	if(1==exponent)
	{
	  return base;
	}
	unsigned int absExponent=(unsigned int)(exponent);
	if(exponent<0) //指数为负数
		absExponent=(unsigned int)(-exponent);
	double result=PowerwihtUnsignedExponent(base,absExponent);
	if(exponent<0)
		result=1.0/result;
	return result;
}
int main()
{
	double result=Power(0,3);
	if(InvalidInput==true)//此处一定要对应用的结果进行InvalidInput检查,看是否正常返回还是出错;
		cout<<"INVALID INPUT!"<<endl;
	else
		cout<<Power(0,3)<<endl;
	system("pause");
	return 0;
}

运行结果:


上面的程序虽然比较考虑到了一些可能出错的情况,但是现在又该考虑效率问题了,上面的程序exponent是多少就会循环多少次。可不可以减少循环的次数呢?

答案是肯定的。看下面的公式你就明白了!


所以:PowerWithUsignedExponent代码如下:

double PowerwihtUnsignedExponent(double base,unsigned int exponent)
{
	double result=1.0;
	result=PowerwihtUnsignedExponent(base,exponent>>1);
	result*=result;
	if((exponent& 0x1)==1)//为奇数;
		result*=base;
	return result;
}

我们用右移运算代替了除2,用位&运算代替了%运算符,这又使代码的效率提高了很多。


你可能感兴趣的:(指数函数,剑指offer,X的N次方)