Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

誤差函數

概要

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

namespace boost{ namespace math{

template <class T>
calculated-result-type erf(T z);

template <class T, class Policy>
calculated-result-type erf(T z, const Policy&);

template <class T>
calculated-result-type erfc(T z);

template <class T, class Policy>
calculated-result-type erfc(T z, const Policy&);

}} // namespaces

函數返回值的類型使用返回值推導法則:來確定,當x是整型的時候,返回值的類型是double,否則返回值是類型是T.

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

說明
template <class T>
calculated-result-type erf(T z);

template <class T, class Policy>
calculated-result-type erf(T z, const Policy&);

返回z的誤差函數erf of z:

template <class T>
calculated-result-type erfc(T z);

template <class T, class Policy>
calculated-result-type erfc(T z, const Policy&);

返回z的誤差函數 的補集:

精確性

下面的表顯示了在不同的平台上使用不同的浮點類型時的峰值誤差(10的-5次方數量級),以及與GSL-1.9, GNU C Lib, HP-UX C 函數庫 Cephes 庫的比較. 除非特地指定了比下面顯示的浮點類型更窄的浮點類型,否則計算結果具有有效零誤差.

表7. erf(z) 出錯率(Errors Rates)

有效數字位數

平台和編譯器

z < 0.5

0.5 < z < 8

z > 8

53

Win32, Visual C++ 8

峰值=0 均值=0

GSL 峰值=2.0 均值=0.3

Cephes 峰值=1.1 均值=0.7

峰值=0.9 均值=0.09

GSL 峰值=2.3 均值=0.3

Cephes 峰值=1.3 均值=0.2

峰值=0 均值=0

GSL 峰值=0 均值=0

Cephes 峰值=0 均值=0

64

RedHat Linux IA32, gcc-3.3

峰值=0.7 均值=0.07

GNU C Lib 峰值=0.9 均值=0.2

峰值=0.9 均值=0.2

GNU C Lib 峰值=0.9 均值=0.07

峰值=0 均值=0

GNU C Lib 峰值=0 均值=0

64

Redhat Linux IA64, gcc-3.4.4

峰值=0.7 均值=0.07

GNU C Lib 峰值=0 均值=0

峰值=0.9 均值=0.1

GNU C Lib 峰值=0.5 均值=0.03

峰值=0 均值=0

GNU C Lib 峰值=0 均值=0

113

HPUX IA64, aCC A.06.06

峰值=0.8 均值=0.1

HP-UX C Library Lib 峰值=0.9 均值=0.2

峰值=0.9 均值=0.1

HP-UX C Library Lib 峰值=0.5 均值=0.02

峰值=0 均值=0

HP-UX C Library Lib 峰值=0 均值=0


表8.函數 erfc(z)的出錯率(Errors Rates)

有效數字位數

平台和編譯器

z < 0.5

0.5 < z < 8

z > 8

53

Win32, Visual C++ 8

峰值=0.7 均值=0.06

GSL 峰值=1.0 均值=0.4

Cephes 峰值=0.7 均值=0.06

峰值=0.99 均值=0.3

GSL 峰值=2.6 均值=0.6

Cephes 峰值=3.6 均值=0.7

峰值=1.0 均值=0.2

GSL 峰值=3.9 均值=0.4

Cephes 峰值=2.7 均值=0.4

64

RedHat Linux IA32, gcc-3.3

峰值=0 均值=0

GNU C Lib 峰值=0 均值=0

峰值=1.4 均值=0.3

GNU C Lib 峰值=1.3 均值=0.3

峰值=1.6 均值=0.4

GNU C Lib 峰值=1.3 均值=0.4

64

Redhat Linux IA64, gcc-3.4.4

峰值=0 均值=0

GNU C Lib 峰值=0 均值=0

峰值=1.4 均值=0.3

GNU C Lib 峰值=0 均值=0

峰值=1.5 均值=0.4

GNU C Lib 峰值=0 均值=0

113

HPUX IA64, aCC A.06.06

峰值=0 均值=0

HP-UX C Library 峰值=0 均值=0

峰值=1.5 均值=0.3

HP-UX C Library 峰值=0.9 均值=0.08

峰值=1.6 均值=0.4

HP-UX C Library 峰值=0.9 均值=0.1


測試

這些函數的測試包含兩部分: 基本的合理性測試使用Mathworld's 在線求值產生的抽樣數據,而精度測試的數據使用精度為1000-bits的NTL::RR 庫以及這個庫的實現生成. 注意:這些函數的一般版本和類型特定的版本在內部使用不同的實現,所以這就可以給我們生成相互獨立的測試數據。使用我們的測試數據來測試其它的"已知的良好 (known good)" 庫同樣也提供了一個合理性測試.

實現

所有的這些實現都首先使用通常的反射方程來使得它們的參數為正數:

erf(-z) = 1 - erf(z);

erfc(-z) = 2 - erfc(z);  // 當 -z < -0.5時作為選擇

erfc(-z) = 1 + erf(z);   // 當 -0.5 <= -z < 0時作為選擇

這些函數的一般版本使用不完全γ函數來實現.

當小數 (尾數) 大小是已知的時候(當前針對於 53, 64 和 113-bit 實數, 加上提升為double的單精度的24-bits實數 ) 使用級數的有理逼近由JM發明

對於 z <= 0.5,那麼將會使用erf的有理逼近,這一點是基於erf是一個偶函數且可以使用下面的方式來計算的觀察:

erf(z) = z * (C + R(z*z));

其中 ,針對於的R(z*z)有理逼近進行了絕對誤差的優化: 一旦它的絕對誤差與常量C相比足夠小的話,任何在計算R(z*z)的過程中的捨入誤差將會在計算結果中消失。因結在這個區域中的erf函數和erfc函數的誤差很低:在非常少數的情況下最生一個bit不是正確的.

對於 z > 0.5 ,我們觀察到在一個小的區間[a, b) 上對於一些常量 c.:

erfc(z) * exp(z*z) * z ~ c

因此對於z > 0.5,我們使用下面的方法來計算 erfc:

erfc(z) = exp(-z*z) * (C + R(z - B)) / z;

R(z - B) 也針對於絕對誤差進行了優化, 並且常量C是erfc(z) * exp(z*z) * z 在這個範圍的端點處值的平均值。再一次,一旦R(z - B)的絕對誤差與常量c相比足夠小的話,那麼c+R(z-B)將會進行正確的捨入。並且精確性只依賴於函數exp。實際上,在大多數情況下,誤差被限制到結果的最後一個bit。選擇常量B使得範圍的左端的有理逼近為0。

對於區間 [a, +∞]上的較大的z,上面的逼近修改為:

erfc(z) = exp(-z*z) * (C + R(1 / z)) / z;

PrevUpHomeNext