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

题目:实现函数 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~*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章