Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

運行時基礎的編譯時冪函數

pow 函數高效地計算一個運行時基礎的編譯時整數冪。

概要

#include <boost/math/special_functions/pow.hpp>

namespace boost { namespace math {

template <int N, typename T>
calculated-result-type pow(T base);

template <int N, typename T, class Policy>
calculated-result-type pow(T base, const Policy& policy);

}}
原理以及使用

計算一個在編譯時指數已知的數的冥是程序員的一個常見的需求。在這種情況下,通常的做法是避免由C上的函數pow,powf,powl因為如下的硬編碼而帶來的過度的開銷:

// 硬編碼一個 'base' 變量的8th冪
double result = base*base*base*base*base*base*base*base;

然而, 這種表達式的可讀性很差 (知道這個指數的值涉及到數出base出現的次數), 易出錯誤(很容易漏掉一次base的出現),句法上過於龐大, 以及沒有針對性能進行優化.

Boost.Math 中的pow 函數幫助書寫這種表達式,同時又解決了上面的所有的問題:

// 使用math::pow函數來計算變量'base'的8次方
double result = pow<8>(base);

這個表達式現在更短,更易讀,更安全且更快 . 實際上, pow 函數只需要log2(N)次乘法就可以計算出這個計算式的值. 例如在上面的例子中, 上面的表達式與我們手寫的下面的表達式的形式是一樣的, 每個相等的子表達式只計算一次:

//pow<8>(base)的內部效果
double result = ((base*base)*(base*base))*((base*base)*(base*base));

只有3個不同的乘積需要計算.

返回值的類型

返回值的類型使用返回值類型推導法則. 例如:

策略

最後一個策略 參數是可選的並且可以用來控制函數的行為: 如何處理錯誤, 使用哪種層次的精度等等. 參見策略文檔瞭解更多信息。

錯誤處理

當以如下兩種方式來使用pow函數時會出現錯誤:

缺省的錯誤策略是throw_on_error. 一個類似於pow<-2>(0) 將會導致拋出一個 std::overflow_error 異常. 就像上面的鏈接中顯示的那樣, 也可以使用其它的錯誤處理策略:

缺省的未定義結果錯誤的策略是ignore_error, 在它種情況下函數返回 1 因為它是0的冪值的常見選擇. 同樣, 也可以使用其它的錯誤處理策略:

這裡是一個定制錯誤處理機制的例子,在這裡,我們想要指定在出現錯誤的情況下返回的值。 因此我們使用user_error 策略,通過通過一個以user_error模板化的overflow_error的實例作為第二個參數。

// 首先我們打開 boost::math::policies 名字空間 並且通過讓它
// 在出錯情況返回我們想要的值的形式來定義 `user_overflow_error`
// (在這個例子中,出錯情況下返回的值是-1)

namespace boost { namespace math { namespace policies {
template <class T>
T user_overflow_error(const char*, const char*, const T&)
{ return -1; }
}}}


// 然後我們調用函數 pow 並表明我們想要使用 user_error 策略
using boost::math::policies;
double result = pow<-5>(base, policy<overflow_error<user_error> >());

// 現在我們可以測試返回值,如果需要的話還可以處理錯誤情況:
if (result == -1)
{
    // 出現一個錯誤, 進行一些處理...
}

另外一種方式是通過使用BOOST_MATH_OVERFLOW_ERROR_POLICY宏來重定義缺省的overflow_error策略. 一旦像上面那樣定義了函數user_overflow_error,我們可以使用下面的方法來實現同樣的效果:

// 重定義缺省的 error_overflow 策略
#define BOOST_MATH_OVERFLOW_ERROR_POLICY user_error
#include <boost/math/special_functions/pow.hpp>

// 比這一點開始, 不再需要在策略中傳遞一個參數, 
//下面的調用在出現錯誤的情況下會返回-1
double result = pow<-5>(base);
致謝

Bruno Lalande 將這個補充提交到 Boost.Math庫中

感謝 Joaqu韓 L髉ez Mu駉z 和 Scott McMurray 對改進這個庫的實現所提供的幫助.

參考書目

D.E. Knuth, The Art of Computer Programming, Vol. 2: Seminumerical Algorithms, 2nd ed., Addison-Wesley, Reading, MA, 1981


PrevUpHomeNext