Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

錯誤處理(Error Handling)

快速指南

這個庫對錯誤的處理被拆分為兩個正交的部分( orthogonal parts ):

可能產生的錯誤為:

定義域錯誤(Domain Error)

當函數的一個或多個參數超出範圍時出現這種錯誤。

Pole Error

當特殊的參數引起函數在一個pole處(沒有定義良好的剩餘值(residual value))計算會出現這種錯誤。例如,如果函數tgamma 在-2處計算時,依據你從-2之上還是從-2之下進行逼近,這個函數會逼近不同的極限值。因此,這個函數在-2這個值處不是定義良好的(well defined),並且將會產生一個Pole Eror。

向上溢出錯誤(Overflow Error)

當結果是無限的,或者結果太大以至於不能在函數的返回值的數值類型中表示,那麼將會出現這種錯誤。

向下錯誤溢出錯誤(Underflow Error)

當結果不為0,但是太小以至於不能在函數的返回值的數值類型中表示,那麼將會出現這種錯誤。

Denormalisation Error

當返回值是一個denormalised value時出現這種錯誤。

捨入錯誤(Rounding Error)

當函數truncroundmodf 的參數不能被表示為一個整數,或是超出返回值類型的範圍的時候會出現這種錯誤。

計算錯誤(Evaluation Error)

當出現內部錯誤,使得結果不能被計算的時候出現:這永遠都不應當出現,但是如果出現這種錯誤,可能是因為迭代算法收斂得不夠快。

未定義結果錯誤(Indeterminate Result Error)

當對於傳遞給函數的參數值,函數的結果是未定義的時候會出現這種錯誤。

在每種錯誤情況下所採取的處理方法由當前的策略 來決定。這可以用過設置一些配置宏來在工程範圍(project-wide)來改變策略,或是在名字空間作用域,或是在調用點(通過為調用的函數指定一個特定的策略)改變策略。

可以採取的錯誤處理措施是:

throw_on_error

拋出一個最適合錯誤情況的異常。

errno_on_error

將 ::errno 設置為一個合適的值,並返回最合適的結果。

ignore_error

忽略這個錯誤並返回最合適的值。

user_error

調用一個用戶提供的錯誤處理方法

下面的表中所有的錯誤和採取的錯誤處理措施的排列(permutations),每種錯誤的缺省處理措施以黑體顯示:

對於定義域錯誤( Domain Errors)可採取的措施

措施

行為

throw_on_error

Throws std::domain_error

errno_on_error

設置::errnoEDOM 並返回std::numeric_limits<T>::quiet_NaN()

ignore_error

返回std::numeric_limits<T>::quiet_NaN()

user_error

返回boost::math::policies::user_domain_error: 這個函數必須由用戶定義


對於 Pole Errors可採取的措施

措施

行為

throw_on_error

拋出std::domain_error異常

errno_on_error

設置::errnoEDOM 並返回 std::numeric_limits<T>::quiet_NaN()

ignore_error

返回std::numeric_limits<T>::quiet_NaN()

user_error

返回boost::math::policies::user_pole_error: 這個函數必須由用戶定義


對於溢出錯誤( Overflow Errors )可採取的措施

措施

行為

throw_on_error

拋出std::overflow_error異常

errno_on_error

設置::errnoERANGE 並返回std::numeric_limits<T>::infinity()

ignore_error

返回std::numeric_limits<T>::infinity()

user_error

返回boost::math::policies::user_overflow_error: 這個函數必須由用戶定義


對於向下溢出( Underflow Errors)可採取的措施

措施

行為

throw_on_error

拋出std::underflow_error異常

errno_on_error

設置::errnoERANGE 並返回 0

ignore_error

返回 0

user_error

返回boost::math::policies::user_underflow_error: 這個函數必須由用戶定義


對於 Denorm Errors可採取的措施

措施

行為

throw_on_error

拋出std::underflow_error異常

errno_on_error

設置::errnoERANGE 並返回 denormalised value.

ignore_error

返回 denormalised value.

user_error

返回boost::math::policies::user_denorm_error: 這個函數必須由用戶定義


對於捨入錯誤( Rounding Errors)可採取的措施

措施

行為

throw_on_error

拋出boost::math::rounding_error 異常

errno_on_error

設置::errnoERANGE 並返回一個未指定的值

ignore_error

返回一個未指定的值( unspecified value ).

user_error

返回boost::math::policies::user_rounding_error: 這個函數必須由用戶定義


對於內部計算錯誤( Internal Evaluation Errors)可採取的措施

措施

行為

throw_on_error

拋出boost::math::evaluation_error異常

errno_on_error

設置::errnoEDOM 並返回已查找到的最接近的逼近值.

ignore_error

返回已查找到的最接近的逼近值

user_error

返回boost::math::policies::user_evaluation_error: 這個函數必須由用戶定義


對於未定義結果錯誤( Indeterminate Result Errors)所採取的措施

措施

行為

throw_on_error

拋出std::domain_error異常

errno_on_error

設置::errnoEDOM 並返回與ignore_error相同的值.

ignore_error

返回一個依賴於發生錯誤的函數的缺省值.

user_error

返回boost::math::policies::user_indeterminate_result_error: 這個函數必須由用戶定義


原理

當前庫實現的靈活性是相當明顯的,缺省行為的選擇依據過去的庫的複審過程中的反饋信息:

查找更多信息

有一些預編譯宏來改變缺省策略。參考策略文檔

在策略指南的改變缺省策略中有一個例子。

將一個非法參數(負的自由度)傳遞給一個學生t分佈的的例子的完整代碼在錯誤處理實例中。

各種錯誤情況在下面進行了更詳細的描述。

定義域錯誤(Domain Errors)

當向一個特殊函數傳遞一個超出它所定義的變量範圍的參數的時候,那麼函數返回結果為:

boost::math::policies::raise_domain_error<T>(FunctionName, Message, Val, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息。 Val 是超出範圍的值,且Policy 是當前調用的函數所使用的策略。

這些策略的缺省行為是拋出一個 std::domain_error C++ 異常。但是如果Policy 將忽略錯誤,並設置全局變量 ::errno,那麼將返回一個 NaN 。

選擇這種行為是為了與ISO/IEC 9899:1999 Programming languages - C 以及 Draft Technical Report on C++ Library Extensions, 2005-06-24, section 5.2.1, paragraph 6相兼容:

"如果一個參數的值為NaN,那麼上面聲明的每個函數都應當返回NaN(Not a Number),但它不應當報出定義域錯誤。否則,上面聲明的每個函數都應當對超出定義域的參數報出定義域錯誤:

"這個函數說明的返回條款( Returns clause )明確地指定一個值域以及這些超出指定值域的參數;或者

"對應的數學函數的值有一個非零的虛部(imaginary component); 或者

"對應的數學函數在數學上是未定義的"

"提示 2:一個數學函數是在數學上定義的,對於一個給定的參數集合,如果這個數學參數明確針對那些參數進行了定義,或者如果它的極限值存在並且不依賴於逼近的方向 (A mathematical function is mathematically defined for a given set of argument values if it is explicitly defined for that set of argument values or if its limiting value exists and does not depend on the direction of approach)."

注意,為了在拋出異常時支持具有豐富信息的報錯消息,Message 必須包含一個Boost.Format 可以解析的格式化指定符號:參數Val 對應指定符號被插入到這個報錯消息中。

例如,如果Message 包含一個"%1%" ,那麼它將使用T類型的完全精度的Val 值來替換,其中"%.3g" 將包含 Val 具有3個數字的值,參考Boost.Format 文檔瞭解更多 信息。

在 pole處計算

當給一個特殊函數傳遞了一個在pole處而沒有定義良好的剩餘值(residual value)的參數值的時候,那麼函數返回的結果為:

boost::math::policies::raise_pole_error<T>(FunctionName, Message, Val, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息。 Val 是在pole處的參數的值,且Policy 是當前調用的函數所使用的策略。

這個函數的函數行為是缺省一個std::domain_error 異常。但是可以使用錯誤處理策略 來改變函數的缺省策略,例如改為ignore_error 並返回 NaN。

注意,為了在拋出異常時支持具有豐富信息的報錯消息,Message 必須包含一個Boost.Format 可以解析的格式化指定符號:參數Val 對應指定符號被插入到這個報錯消息中。

例如,如果Message 包含一個"%1%" ,那麼它將使用T類型的完全精度的Val 值來替換,其中"%.3g" 將包含 Val 具有3個數字的值,參考Boost.Format 文檔瞭解更多 信息。

數值溢出(Numeric Overflow)

當特殊函數的結果太大以至於不能存儲在參數的浮點類型中時,那麼函數返回的結果為:

boost::math::policies::raise_overflow_error<T>(FunctionName, Message, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,且Policy 是當前調用的函數所使用的策略。

這個函數的缺省策略的行為是拋出std::overflow_error C++ 異常。但是如果,例如,使用了一個ignore_error 策略,那麼函數返回std::numeric_limits<T>::infinity()。在這種情況下,如果類型T不支持無限值,那麼這個類型的最大值將被返回。

數值向下溢出(Numeric Underflow)

如果特殊函數的結果已知為非零,但是計算結果發生向下溢出為0,那麼函數的返回的結果為:

boost::math::policies::raise_underflow_error<T>(FunctionName, Message, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,且Policy 是當前調用的函數所使用的策略。

函數在缺省情況下返回0。但使用其它的策略,類似於throw_on_error,將拋出一個std::underflow_error C++ 異常。

Denormalisation Errors

特殊函數的計算結果是一個denormalised value z ,那麼函數的返回值是:

boost::math::policies::raise_denorm_error<T>(z, FunctionName, Message, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,且Policy 是當前調用的函數所使用的策略。

函數的缺省行為是返回z值。但是使用其它的策略,類似於throw_on_error 將會拋出一個std::underflow_error C++ 異常。

計算錯誤(Evaluation Errors)

當一個特殊函數計算的結果已知是錯誤的,或者結果是不可計算的,那麼函數調用:

boost::math::policies::raise_evaluation_error<T>(FunctionName, Message, Val, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,Val是引發錯誤的值,且Policy 是當前調用的函數所使用的策略。

The default behaviour of this function is to throw a boost::math::evaluation_error.

注意,為了在拋出異常時支持具有豐富信息的報錯消息,Message 必須包含一個Boost.Format 可以解析的格式化指定符號:參數Val 對應指定符號被插入到這個報錯消息中。

例如,如果Message 包含一個"%1%" ,那麼它將使用T類型的完全精度的Val 值來替換,其中"%.3g" 將包含 Val 具有3個數字的值,參考Boost.Format 文檔瞭解更多 信息。

未定義的結果錯誤(Indeterminate Result Errors)

當對於傳遞給特殊函數的參數值,特殊函數的結果是一個未定義的值時,那麼返回的返回值為:

boost::math::policies::raise_overflow_error<T>(FunctionName, Message, Val, Default, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,Val是未定義的值,缺省情況下是一個必須被ignore_error 和 errno_on_error策略返回的值, 且Policy 是當前調用的函數所使用的策略。

這個函數的缺省策略是ignore_error:注意,這種錯誤類型為結果是數學上未定義的或是未知的值的情況保留,但是沒有一個返回值應當是多少的約定(convention):例如,C99標準規定 00 為 1,儘管這個值在數學上是未知的。

捨入錯誤(Rounding Errors)

round, truncmodf函數使用一個沒有整數表示(integer representation)的參數調用時調用,或者參數太大以至於不能在返回值的類型中表示出來,那麼返回值的結果是對於下面函數的調用:

boost::math::policies::raise_rounding_error<T>(FunctionName, Message, Val, Policy);

其中T 是傳遞給函數的浮點類型,FunctionName 是函數的名字,Message 是描述問題的報錯消息,Val是引發錯誤的參數值,且Policy 是當前調用的函數所使用的策略。

The default behaviour of this function is to throw a boost::math::rounding_error.

注意,為了在拋出異常時支持具有豐富信息的報錯消息,Message 必須包含一個Boost.Format 可以解析的格式化指定符號:參數Val 對應指定符號被插入到這個報錯消息中。

例如,如果Message 包含一個"%1%" ,那麼它將使用T類型的完全精度的Val 值來替換,其中"%.3g" 將包含 Val 具有3個數字的值,參考Boost.Format 文檔瞭解更多 信息。

類型轉換帶來的錯誤(Errors from typecasts)

為了在結果中確保完全的機器精度( machine precision),許多特殊函數使用比參數精度高的類型進行計算:例如一個參數為float的函數在內部可能會使用double精確度來計算結果。上面出現的很多錯誤可能不會在計算的過程中出現,但在將計算結果轉換為更窄的返回值類型時會出現上面的錯誤。這個函數

template <class T, class Policy, class U>
T checked_narrowing_cast(U const& val, const char* function);

用於進行這些轉換,並且在出現向上溢出(overflow)向下溢出(underflow)denormalisation錯誤時調用上面的錯誤處理方法。


PrevUpHomeNext