![]() |
Home | Libraries | People | FAQ | More |
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個不同的乘積需要計算.
返回值的類型使用返回值類型推導法則. 例如:
float類型, 返回值的類型是float.
long double 類型,
返回值類型是long double.
double.
最後一個策略 參數是可選的並且可以用來控制函數的行為: 如何處理錯誤, 使用哪種層次的精度等等. 參見策略文檔瞭解更多信息。
當以如下兩種方式來使用pow函數時會出現錯誤:
缺省的錯誤策略是throw_on_error.
一個類似於pow<-2>(0) 將會導致拋出一個 std::overflow_error
異常. 就像上面的鏈接中顯示的那樣, 也可以使用其它的錯誤處理策略:
errno_on_error: 設置::errno為ERANGE 然後返回std::numeric_limits<T>::infinity().
ignore_error: 返回std::numeric_limits<T>::infinity().
user_error: 返回boost::math::policies::user_overflow_error: 這個函數必須由用戶定義.
缺省的未定義結果錯誤的策略是ignore_error,
在它種情況下函數返回 1 因為它是0的冪值的常見選擇. 同樣, 也可以使用其它的錯誤處理策略:
throw_on_error: 拋出std::domain_error異常
errno_on_error: 設置::errno
為EDOM 然後返回 1.
user_error: 返回boost::math::policies::user_indeterminate_result_error: 這個函數必須由用戶定義.
這裡是一個定制錯誤處理機制的例子,在這裡,我們想要指定在出現錯誤的情況下返回的值。 因此我們使用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