问题
实现函数求一个浮点数的整数次方。不得使用库函数,同时不考虑大数。(实现类似于power的功能)
例子:1.2的2次方为1.44,
2的3次方为8
思路
看起来比较简单,但是有以下地方需要注意:
1. 当指数为负数的时候,需要对指数求绝对值,然后算出次方的结果之后再取倒数
2. 底数为0且指数为负数时,需要对0进行求倒数的错误处理方式
3. 0的0次方在数学上没有意义,需要单独考虑处理,输出0或者1.
4. 判断底数是否等于0时,不能直接base == 0赋值,因为在计算机中表示小数(包括float和double型小数)时都有误差,判断两个小数是否相等,只能判断它们之差的绝对值是不是在很小的范围。比如小于0.0000001(这里取7位小数),就可以认为它们相等。
5. 如果指数过大,要进行适当的优化,就比如指数等于32位,照常理来说需要做31次乘法,但如果知道了16次方,只要在16次方的基础上进行平方一次就好了。
具体代码
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)
//{
// double result = 1.0;
// for(int i = 1; i <= exponent; ++i)
// {
// result *= base;
// }
// return result;
//}
//递归实现,提高效率的算法
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;
}
int _tmain(int argc, _TCHAR* argv[])
{
double iBase = 0;
int iExponent = 0;
cout<<"Please input a double as base:"<<endl;
cin>>iBase;
cout<<endl;
cout<<"Please input a integer as exponent"<<endl;
cin>>iExponent;
cout<<endl;
double iResult = PowerWithUnsignedExponent(iBase, iExponent);
cout<<"Result is :"<<iResult<<endl;
cout<<endl;
system("Pause");
return 0;
}
测试用例:
把底数和指数分别设为正数,负数和零。
结果截图:
思考
- 在提高效率的算法中,用右移运算符代替了除以2,用位与运算符代替了求余运算符(%)来判断一个数是奇数还是偶数。因为位运算符的效率比乘除法及求余运算的效率高点。
- 在进行浮点型计算时,要考虑浮点型在计算机中的表示情况和判断相等的情况。
3.在有涉及触发计算的时候,要考虑分母不为0的错误处理。