1. 程式人生 > >power(乘冪)函數剖析

power(乘冪)函數剖析

nec 例如 blog 繼續 -s 記錄 計算 element pre

近來學習STL,看到power函數的實現感覺挺有趣,記錄一下。

1. 一般情況下,我自己要實現乘冪函數會這樣實現:

int power(int x,size_t n)
{
    int result = 1;
    while (n--)
        result *= x;
    return result;
}

這樣即使實現,這裏的時間復雜度和n有關,時間復雜度為0(n)。

2. 看了stl源碼實現是這樣:

// Returns __x ** __n, where __n >= 0.  _Note that "multiplication"
// is required to be associative, but not necessarily commutative.  
//意思是multiplication要滿足結合律,但不需要滿足交換律 template <class _Tp, class _Integer, class _MonoidOperation> _Tp __power(_Tp __x, _Integer __n, _MonoidOperation __opr) //這裏第三個參數是一個二元操作函數 { if (__n == 0) return identity_element(__opr); //返回1 else { while ((__n & 1) == 0
) //如果n為偶數 { __n >>= 1; __x = __opr(__x, __x); } _Tp __result = __x; __n >>= 1; while (__n != 0) { __x = __opr(__x, __x); if ((__n & 1) != 0) //如果n為奇數 __result = __opr(__result, __x); __n
>>= 1; } return __result; } } template <class _Tp, class _Integer> inline _Tp __power(_Tp __x, _Integer __n) { return __power(__x, __n, multiplies<_Tp>()); } // Alias for the internal name __power. Note that power is an extension, // not part of the C++ standard. template <class _Tp, class _Integer, class _MonoidOperation> inline _Tp power(_Tp __x, _Integer __n, _MonoidOperation __opr) //也可以自定義,傳進去一個函數 { return __power(__x, __n, __opr); } template <class _Tp, class _Integer> inline _Tp power(_Tp __x, _Integer __n) //默認情況下是乘冪 { return __power(__x, __n); }

這裏:當n為偶數時,X^n=(X^2)^(2/n),此時看2/n是否還是偶數,如果是則繼續,否則,轉向n是奇數的情況;

當n為奇數時,X^n=X*X^(n-1);

例如計算5^6=(5^2)^3,也就是計算25^3。

這種情況和第三種情況類似,只是當n開始為偶數時,比第三種方法的效率更高,n為奇數時,和第三種方法時間復雜度一樣。

3. 看了還有一種實現,和stl源碼差不多,只是表示更簡潔,和第二種情況相比效率會差點:

int power(int x, size_t n)
{
    if(n == 0)
        return 1;
    int result = 1;
    while(n)
    {
        if(n & 1)                    //n為奇數時
            result *= x;            
        n >>= 1;
        x *= x;                 
    }
}

如計算5^6是6化為二進制為0110,所以這裏5^6=5^2*5^4,這裏時間復雜度為0((log2n)+1)

power(乘冪)函數剖析