Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
查找尺度(標準差)實例(Find Scale Example)

首先我們需要包含一些頭文件來訪問正態分佈(Normal Distribution),查找尺度(scale)的算法(以及標準輸出)。

#include <boost/math/distributions/normal.hpp> // normal_distribution
  using boost::math::normal; // typedef 提供的缺省類型為 double.
#include <boost/math/distributions/find_scale.hpp>
  using boost::math::find_scale; 
  using boost::math::complement; // 如果我們想要使用補集版本( complement version ).
  using boost::math::policies::policy; // 指定錯誤處理策略.

#include <iostream>
  using std::cout; using std::endl;
#include <iomanip>
  using std::setw; using std::setprecision;
#include <limits>
  using std::numeric_limits;

對於這個例子,我們將使用標準正態分佈(Normal Distribution), 位置(location) (均值)為0且標準差為1。出於方便性的考慮,這也是構造函數的缺省值。

normal N01;  // 缺省的 '標準' 正態分佈均值為0
double sd = 1.; // 標準差為 1.

假設我們要查找一個不同的正態分佈的標準差,使得僅有數量為p (在這裡為 0.001 或 0.1%) 的隨機變量位於一個特定的界限之下 (這裡為 -2. 標準差).

double z = -2.; // z to give prob p
double p = 0.001; // only 0.1% below z = -2

cout << "Normal distribution with mean = " << N01.location()  // aka N01.mean()
  << ", standard deviation " << N01.scale() // aka N01.standard_deviation()
  << ", has " << "fraction <= " << z 
  << ", p = "  << cdf(N01, z) << endl;
cout << "Normal distribution with mean = " << N01.location()
  << ", standard deviation " << N01.scale()
  << ", has " << "fraction > " << z
  << ", p = "  << cdf(complement(N01, z)) << endl; // Note: uses complement.

Normal distribution with mean = 0 has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0 has fraction > -2, p = 0.97725

注意 p = 0.02 而不是我們的目標 0.001,現在我們可以使用函數find_scale 來給定一個新的標準差。

double l = N01.location();
double s = find_scale<normal>(z, p, l);
cout << "scale (standard deviation) = " << s << endl;

輸出為:

scale (standard deviation) = 0.647201

顯示我們需要將標準差從1 減少到 0.65.

然後我們通過使用新的標準差來構造一個新的分佈來檢查我們已經達到目標:

normal np001pc(N01.location(), s);

並重新計算低於 (以及超過) 我們選定界限的百分比。

cout << "Normal distribution with mean = " << l 
  << " has " << "fraction <= " << z 
  << ", p = "  << cdf(np001pc, z) << endl;
cout << "Normal distribution with mean = " << l 
  << " has " << "fraction > " << z 
  << ", p = "  << cdf(complement(np001pc, z)) << endl;

Normal distribution with mean = 0 has fraction <= -2, p = 0.001
Normal distribution with mean = 0 has fraction > -2, p = 0.999

控制函數 find_scale 中錯誤的處理方式

我們也可以控制處理各種錯誤的策略。例如,我們可以定義一個新的策略(可能不是很明智) 來忽略定義域錯誤 ('壞的' 參數)。

除非我們使用了 boost::math 名字空間,我們將需要:

using boost::math::policies::policy;
using boost::math::policies::domain_error;
using boost::math::policies::ignore_error;

雖然沒有被要求,但使用 typedef 是很方便的,尤其是如果重複使用, 就像下面的多個例子顯示的那樣:

typedef policy<domain_error<ignore_error> > ignore_domain_policy;
// find_scale 使用一個新的策略, 使用 typedef.
l = find_scale<normal>(z, p, l, ignore_domain_policy());
// Default policy policy<>, needs using boost::math::policies::policy;

l = find_scale<normal>(z, p, l, policy<>());
// 缺省策略,完全指定.
l = find_scale<normal>(z, p, l, boost::math::policies::policy<>());
// 新的策略,沒有使用 typedef.
l = find_scale<normal>(z, p, l, policy<domain_error<ignore_error> >());

如果我們想要表示一個概率,比如說 0.999,那就是一個補集(complement),1 - p ,我們幾乎不需要思考就可以寫出 find_scale<normal>(z, 1 - p, l), 但是 取而代之, 使用補集版本(complements)

z = -2.;
double q = 0.999; // = 1 - p; //  0.001的補集.
sd = find_scale<normal>(complement(z, q, l));

normal np95pc(l, sd); // 同樣的 standard_deviation  但調整均值mean
cout << "Normal distribution with mean = " << l << " has " 
  << "fraction <= " << z << " = "  << cdf(np95pc, z) << endl;
cout << "Normal distribution with mean = " << l << " has " 
  << "fraction > " << z << " = "  << cdf(complement(np95pc, z)) << endl;

當你得到一個類似於下面的警告消息的時候,就很容易避免這種錯誤的方式:

Message from thrown exception was:
   Error in function boost::math::find_scale<Dist, Policy>(complement(double, double, double, Policy)):
   Computed scale (-0.48043523852179076) is <= 0! Was the complement intended?

缺省的錯誤處理策略是使用這個消息來拋出異常,但是如果你選擇一個忽略錯誤的策略,負的尺度(scale)就會悄悄地返回(原本是不可能的)。

參考 find_scale_example.cpp 查看完整代碼:程序的輸出類似於下面:

Example: Find scale (standard deviation).
Normal distribution with mean = 0, standard deviation 1, has fraction <= -2, p = 0.0227501
Normal distribution with mean = 0, standard deviation 1, has fraction > -2, p = 0.97725
scale (standard deviation) = 0.647201
Normal distribution with mean = 0 has fraction <= -2, p = 0.001
Normal distribution with mean = 0 has fraction > -2, p = 0.999
Normal distribution with mean = 0.946339 has fraction <= -2 = 0.001
Normal distribution with mean = 0.946339 has fraction > -2 = 0.999


PrevUpHomeNext