Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
錯誤處理(Error Handling)實例

參考錯誤處理文檔 瞭解錯誤處理機制的詳細細節,包括常見的,傳遞給分佈和函數的「壞的(bad)」參數,以及如何使用策略 來控制錯誤處理方式 。

但是在缺省情況下,對於定義域錯誤(domain errors), 函數的極(pole)錯誤(pole errors),數值溢出( numeric overflow),以及內部計算錯誤,錯誤處理方式是拋出異常 。 為了避免拋出異常,而在錯誤發生的情況下獲得一個合適的返回值,通常使用一個NaN (定義域錯誤(domain errors), 函數的極錯誤(pole errors)或者內部錯誤( internal errors) ),或者是一個無限值 (溢出)你需要改變策略。

下面的例子顯示了當遇到一個非法參數的時候,設置 BOOST_MATH_DOMAIN_ERROR_POLICY 的作用,我們將給學生t分佈(student's t distribution)傳遞一個負的自由度參數(egrees of freedom parameter)。

因為我們知道這是一個單文件的程序,我們可以簡單地在源文件的頂部添加:

#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error

來將策略更改為在發生定義域錯誤的簡單在返回一個NaN。另一方面我們可以使用:

#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error

來確保當發生定義錯誤的時候設置::errno 並返回 NaN。

僅在這個程序只包含一個編譯單元(translation unit) 我們將這個 define 放在任何的#include 之前 這種做法才是安全的。 注意:如果我們將 define 如果到#include後面的時候不會有任何作用! 類似於下面的:

warning C4005: 'BOOST_MATH_OVERFLOW_ERROR_POLICY' : macro redefinition

是一個我們的#define不會有預期效果的肯定標記( certain sign )。

我們使用必需包含的頭文件來開始我們的程序:

// Boost
#include <boost/math/distributions/students_t.hpp>
   using boost::math::students_t;  //  students_t(df, t)的概率.

// std
#include <iostream>
   using std::cout;
   using std::endl;

#include <stdexcept>
   using std::exception;

接下來,我們將定義程序的main函數來使用一個非法的自由度參數(degrees of freedom parameter)來調用學生t分佈(student's t distribution),這個程序計劃處理異常或NaN。

int main()
{
   cout << "Example error handling using Student's t function. " << endl;
   cout << "BOOST_MATH_DOMAIN_ERROR_POLICY is set to: "
      << BOOST_STRINGIZE(BOOST_MATH_DOMAIN_ERROR_POLICY) << endl;

   double degrees_of_freedom = -1; // 一個非法參數!
   double t = 10;

   try
   {
      errno = 0;
      students_t dist(degrees_of_freedom); // 如何拋出異常被允許,在這裡拋出異常
      double p = cdf(dist, t);
      // 測試其它方式報告的錯誤:
      if((boost::math::isnan)(p))
      {
         cout << "cdf returned a NaN!" << endl;
         cout << "errno is set to: " << errno << endl;
      }
      else
         cout << "Probability of Student's t is " << p << endl;
   }
   catch(const std::exception& e)
   {
      std::cout <<
         "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
   }

   return 0;
} // int main()

下面是使用缺省編譯選項時的程序輸出 (的確拋出了異常):

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: throw_on_error

Message from thrown exception was:
   Error in function boost::math::students_t_distribution<double>::students_t_distribution:
   Degrees of freedom argument is -1, but must be > 0 !

另一方面我們可以使用:

#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error

來編譯,現在程序的輸出為:

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: ignore_error
cdf returned a NaN!
errno is set to: 0

最後,讓我們使用:

#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error

來編譯,輸出結果為:

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: errno_on_error
cdf returned a NaN!
errno is set to: 33

[Caution] 注意

如果已經允許拋出異常(缺省設置),但是你沒有 使用 try & catch ,那麼程序將以一個未捕獲的異常中止(terminate),並且可能abort。

因此,為了獲取有幫助的報錯消息,對於大多數的應用程序而言,推薦允許拋出所有的異常並使用 try & catch。

然而,為了簡化代碼,對於大多數的例子都沒有這樣做。


PrevUpHomeNext