C++剑指offer_面试题11_数值的整数次方(*)

来源:互联网 发布:淘宝服装图片拍摄技巧 编辑:程序博客网 时间:2024/06/07 03:26

题目:实现函数 double Power(double base, int exponent),求 base 的 exponent 次方。不得使用库函数,同时不需要考虑大数问题。 

通过这道题,了解一些不曾注意的知识点:

1、变量命名要合理且明了

2、需确保代码的完整性,从三个角度下手:

      1)功能测试:确保主体功能

      2)边界测试:考虑各种边界值

      3)负面测试:考虑各种可能的错误输入

3、代码高效性,性能测试:考虑代码的执行效率

4、3种错误处理方法:

      1)用函数返回值来告知调用者是否出错

      2)当错误发生时,设置一个全局变量

      3)异常,当函数运行出错时,抛出一个异常。

对于上述题目,其解答如下:

解决方法一:

只实现了基本功能,即指数 为正的情况,其他输入毫无考虑。

[cpp] view plain copy
  1. double Power0(double base, int exponent)  
  2. {  
  3.     double result = 1.0;  
  4.     for(int i = 1; i < exponent; i++)  
  5.     {  
  6.         result *= base;  
  7.     }  
  8.     return result;  
  9. }  
解决方法二:

考虑代码的完整性

[cpp] view plain copy
  1. /**用于判定两个 double 型数据是否相等,不能直接用 == ,只能用两者之间的差值在一个很小的范围内来判断*/  
  2. bool Equal_double(double num1,double num2)  
  3. {  
  4.     if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))  
  5.         return true;  
  6.     else  
  7.         return false;  
  8. }  
  9. /**指数为正的时候*/  
  10. double Power_with_unsigned_int(double base,unsigned int exponent)  
  11. {  
  12.     double result = 1.0;  
  13.     for(unsigned int i = 1; i <= exponent; i++)  
  14.     {  
  15.         result *= base;  
  16.     }  
  17.     return result;  
  18. }  
  19.   
  20. bool g_InvalidInput  = false;     /**设定一个全局变量来表示无效输入,变量名要明确*/  
  21. double Power1(double base, int exponent)  
  22. {  
  23.     /*考虑基数为0.0的情况*/  
  24.     if(Equal_double(base,0.0) && exponent <= 0)  
  25.     {  
  26.         g_InvalidInput = true;  
  27.         return 0.0;  
  28.     }  
  29.     else if(Equal_double(base,0.0) && exponent > 0)  
  30.         return 0.0;  
  31.   
  32.     unsigned int absExponent = (unsigned int)(exponent);  
  33.     if(exponent < 0)  
  34.         absExponent = (unsigned int)(-exponent);  
  35.   
  36.     //cout << "absExponent = " << absExponent << endl;  
  37.   
  38.     double result = Power_with_unsigned_int(base,absExponent);  
  39.     /*指数不为正的时候,结果倒置*/  
  40.     if(exponent < 0)  
  41.         result = 1.0 / result;  
  42.   
  43.     return result;  
  44. }  
解决方法三:

考虑代码性能,如 2^16 = (2^8)^2 = ((2^4)^2)^2 ........等依次类推,这样减少了很多重复计算,因此改动 上面的代码的一部分:

[cpp] view plain copy
  1. double Power_with_unsigned_int_efficiently(double base, unsigned int exponent)  
  2. {  
  3.     if(exponent == 0)  
  4.         return 1;  
  5.     if(exponent == 1)  
  6.         return base;  
  7.     double result = Power_with_unsigned_int_efficiently(base, exponent >> 1);  
  8.     result *= result;  
  9.     if(exponent & 0x1 == 1)   //如果是奇数再乘以一个base,%2==0,等于0表示是偶数  
  10.         result *= base;  
  11.   
  12.     return result;  
  13. }  
上面的代码,

1、使用递归(思考上面的过程,有助于理解递归

2、用 位运算,左移一位,代表 除以2,用 与运算 代替取余(%2)来判断是否是奇数。位运算效率更加高。

通过上面这道题,学到了:

1、简单问题,更要考虑全面

2、如何判定两个小数是否相等,不能用“==”,而是要比较两者之间的差值的绝对值,在一个很小的范围内。

3、善用 位运算,可以提高效率。

4、不要把递归想的太复杂

【对照上面的代码来看,如果你考虑每一步的递归过程(包括怎么递归,怎么返回上一步),会很复杂,

  但是整体来看,就是 一步递归 应该干的事,对于本题来说,就是 result *= result;   其他几个 if 判断条件是整体过程需要考虑的】

0 0
原创粉丝点击