劍指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~*/

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