题目:
实现函数double Power(double base,int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
double Power(double base,int exponent)
{
double result=1.0;
for(int i=1;i<=exponent;i++)
result*=base;
return result;
}
该做法没有考虑指数小于1的情况,仅仅包括了指数为正数的情况。
当指数为负数的时候,可以先对指数求绝对值,然后算出次方的结果之后再取倒数。当底数为0且指数为负数时,需要选用下面三种方法之一来告知函数调用者出现的错误:
- 返回值告知,windows中很多API返回值为0表示调用成功,而返回值不为0表示API调用过程出错。
- 设置全局变量
- 抛出异常
bool g_InvalidInput=false;
double Power(double base,int exponent)
{
g_InvalidInput=false;
if(equal(base,0.0) && exponent<0)
{
g_InvalidInput=true;
return 0.0;
}
unsigned int absExponent=(unsigned int)(exponent);
if(exponent<0)
absExponent=(unsigned int)(-exponent);
double result=PowerWithUnsignedExponent(base,absExponent);
if(exponent<0)
result=1.0/result;
return result;
}
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
double result=1.0;
for(int i=1;i<=exponent;i++)
result*=base;
return result;
}
//在判断底数是否为0时,不能直接写base==0,因为计算机内表示小数时都有误差。
//判断两个小数是否相等,只能判断它们之差的绝对值是都在一个很小的范围内
bool equal(double num1,double num2)
{
if((num1-num2>-0.0000001) && (num1-num2<0.0000001))
return true;
else
return false;
}
继续优化,可以用一个比较简单的方法实现PowerWithUnsignedExponent函数。
假如要求32次方,可以在16次方的基础上平方,而16次方是8次方的平方,以此类推。
除此之外,由于位运算比乘数法、求余运算的效率高很多,故可以用右移运算代替除以2等等。
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
if(exponent==0)
return 1;
if(exponent==1)
return base;
double result=PowerWithUnsignedExponent(base,exponent>>1);
result*=result;
//用位运算代替求余运算符
if(exponent & 0x1==1)
result*=base;
return result;
}
下面贴出完整代码以及测试结果:
#include <iostream>
#include <cmath>
bool g_InvalidInput=false;
bool equal(double num1,double num2)
{
if((num1-num2)>-0.0000001 && (num1-num2)<0.0000001)
return true;
else
return false;
}
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
if(exponent==0)
return 1;
if(exponent==1)
return base;
double result=PowerWithUnsignedExponent(base,exponent>>1);
result*=result;
if((exponent & 0x1)==1)
result*=base;
return result;
}
double Power(double base,int exponent)
{
g_InvalidInput=false;
if(equal(base,0.0) && exponent<0)
{
g_InvalidInput=true;
return 0.0;
}
unsigned int absExponent=(unsigned int)(exponent);
if(exponent<0)
absExponent=(unsigned int)(-exponent);
double result=PowerWithUnsignedExponent(base,absExponent);
if(exponent<0)
result=1.0/result;
return result;
}
void Test(const char* testName, double base, int exponent, double expectedResult, bool expectedFlag)
{
double result = Power(base, exponent);
if (equal(result, expectedResult) && g_InvalidInput == expectedFlag)
std::cout << testName << " passed" << std::endl;
else
std::cout << testName << " FAILED" << std::endl;
}
int main(int argc, char* argv[])
{
// 底数、指数都为正数
Test("Test1", 2, 3, 8, false);
// 底数为负数、指数为正数
Test("Test2", -2, 3, -8, false);
// 指数为负数
Test("Test3", 2, -3, 0.125, false);
// 指数为0
Test("Test4", 2, 0, 1, false);
// 底数、指数都为0
Test("Test5", 0, 0, 1, false);
// 底数为0、指数为正数
Test("Test6", 0, 4, 0, false);
// 底数为0、指数为负数
Test("Test7", 0, -4, 0, true);
return 0;
}