剑指Offer面试题11
题目:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
分析:
考虑不够全面的错误思路:
由于不考虑大数的问题,有一种简单的思路直接相乘。
但是这个没有考虑到指数是0或者指数小于1的情况,只考虑了指数是正数的情况。
double Power(double base,int exponent)
{
double result = 1.0;
for(int i = 1;i <= exponent;i++)
{
result *= base;
}
return result;
}
全面但不够高效的方法:
1、先判断指数是否为负数,用flag来记录指数的正负
2、求出指数的绝对值,并求出指数为正数的情况下的结果
3、判断指数是不是负数,是负数,则取倒数
4、提示:实数相等的判断,参考equal函数。
class Solution {
public:
//判断两个实数是否相同
bool equal(double a,double b)
{
if(abs(a - b) < 0.0000001)
{
return true;
}
else
{
return false;
}
}
double Power(double base, int exponent)
{
double result = 1.0; //来存储最后的结果
bool flag = 1; //用来判断是不是负数的情况
unsigned int absExponent = (unsigned int)(exponent); //absExponent用来保存取绝对值后的数值
if(exponent == 0)
{
return result;
}
//由于此处要判断浮点数类型的相等,需要写一个equal()函数来判断
//当底数为0且指数为负数时,会造成分母是0的情况,会导致程序运行出错
if(equal(base,0.0) && exponent < 0)
{
return -123;
}
//用absExponent 来保存指数的绝对值
if(exponent < 0)
{
flag = 0;
absExponent = (unsigned int)(- exponent);
}
//算出指数为正数的情况下的结果
for(int i = 0;i < absExponent;i++)
{
result *= base;
}
//判断指数是否是负数的情况,若是,结果取倒数
if(flag == 0)
{
result = 1.0/result;
}
return result;
}
};
全面且高效的方法:
如果输入的指数为32,我们在函数中写的循环中要做31次乘法。
我们可以换个思路:
1、目标是求一个整数的32次方,可以先计算它的16次方
2、然后在16次方上再平方一次就可以了
3、而16次方是8次方的平方
4、这样以此类推。求32次方要进行5次乘法,先求平方,在平方的基础上求4次方,在4次方的基础上求8次方,在8次方的基础上求16次方,在16次方的基础上求32次方。
所以可以用一下公式:
class Solution
{
public:
//指数为整数时的计算方法
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
if(exponent == 0)
{
return 1;
}
if(exponent == 1)
{
return base;
}
//此处采用位与运算来代替除以2。因为位运算的效率比乘除法及求余运算的效率要高很多。
double result = PowerWithUnsignedExponent(base,exponent >> 1);
result *= result;
//指数为奇数的情况
if(exponent & 0x1 == 1)
{
result *= base;
}
return result;
}
bool equal(double a,double b)
{
if(abs(a - b) < 0.0000001)
{
return true;
}
else
{
return false;
}
}
double Power(double base, int exponent)
{
//absExponent用来保存取绝对值后的数值
unsigned int absExponent = (unsigned int)(exponent);
//由于此处要判断浮点数类型的相等,需要写一个equal()函数来判断
//当底数为0且指数为负数时,会造成分母是0的情况,会导致程序运行出错
if(equal(base,0.0) && exponent < 0)
{
return 0.0;
}
if(exponent < 0)
{
absExponent = (unsigned int)(- exponent);
}
double result = PowerWithUnsignedExponent(base,absExponent);
if(exponent < 0)
{
result = 1.0/result;
}
return result;
}
};