题目:实现函数 double Power(double base, int exponent),求 base 的 exponent 次方。不得使用库函数,同时不需要考虑大数问题。
通过这道题,了解一些不曾注意的知识点:
1、变量命名要合理且明了
2、需确保代码的完整性,从三个角度下手:
1)功能测试:确保主体功能
2)边界测试:考虑各种边界值
3)负面测试:考虑各种可能的错误输入
3、代码高效性,性能测试:考虑代码的执行效率
4、3种错误处理方法:
1)用函数返回值来告知调用者是否出错
2)当错误发生时,设置一个全局变量
3)异常,当函数运行出错时,抛出一个异常。
对于上述题目,其解答如下:
解决方法一:
只实现了基本功能,即指数 为正的情况,其他输入毫无考虑。
double Power0(double base, int exponent)
{
double result = 1.0;
for(int i = 1; i < exponent; i++)
{
result *= base;
}
return result;
}
解决方法二:
考虑代码的完整性
/**用于判定两个 double 型数据是否相等,不能直接用 == ,只能用两者之间的差值在一个很小的范围内来判断*/
bool Equal_double(double num1,double num2)
{
if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
return true;
else
return false;
}
/**指数为正的时候*/
double Power_with_unsigned_int(double base,unsigned int exponent)
{
double result = 1.0;
for(unsigned int i = 1; i <= exponent; i++)
{
result *= base;
}
return result;
}
bool g_InvalidInput = false; /**设定一个全局变量来表示无效输入,变量名要明确*/
double Power1(double base, int exponent)
{
/*考虑基数为0.0的情况*/
if(Equal_double(base,0.0) && exponent <= 0)
{
g_InvalidInput = true;
return 0.0;
}
else if(Equal_double(base,0.0) && exponent > 0)
return 0.0;
unsigned int absExponent = (unsigned int)(exponent);
if(exponent < 0)
absExponent = (unsigned int)(-exponent);
//cout << "absExponent = " << absExponent << endl;
double result = Power_with_unsigned_int(base,absExponent);
/*指数不为正的时候,结果倒置*/
if(exponent < 0)
result = 1.0 / result;
return result;
}
解决方法三:
考虑代码性能,如 2^16 = (2^8)^2 = ((2^4)^2)^2 ........等依次类推,这样减少了很多重复计算,因此改动 上面的代码的一部分:
double Power_with_unsigned_int_efficiently(double base, unsigned int exponent)
{
if(exponent == 0)
return 1;
if(exponent == 1)
return base;
double result = Power_with_unsigned_int_efficiently(base, exponent >> 1);
result *= result;
if(exponent & 0x1 == 1) //如果是奇数再乘以一个base,%2==0,等于0表示是偶数
result *= base;
return result;
}
上面的代码,
1、使用递归(思考上面的过程,有助于理解递归)
2、用 位运算,左移一位,代表 除以2,用 与运算 代替取余(%2)来判断是否是奇数。位运算效率更加高。
通过上面这道题,学到了:
1、简单问题,更要考虑全面
2、如何判定两个小数是否相等,不能用“==”,而是要比较两者之间的差值的绝对值,在一个很小的范围内。
3、善用 位运算,可以提高效率。
4、不要把递归想的太复杂
【对照上面的代码来看,如果你考虑每一步的递归过程(包括怎么递归,怎么返回上一步),会很复杂,
但是整体来看,就是 一步递归 应该干的事,对于本题来说,就是 result *= result; 其他几个 if 判断条件是整体过程需要考虑的】
/*点滴积累,我的一小步O(∩_∩)O~*/