2009-08-20 21 views
10

整数の範囲の開始と終了が与えられた場合、この範囲の間に正規分布したランダムな整数を計算するにはどうすればよいですか?整数範囲から正規分布乱数を生成する方法は?

私は、正規分布が+ +無限大になることを理解しています。私は尾部がカットオフできるので、ランダムが範囲外で計算されると、再計算することができます。これは、範囲内の整数の確率を高めますが、この効果が許容できる限り(< 5%)、問題ありません。

public class Gaussian 
{ 
    private static bool uselast = true; 
    private static double next_gaussian = 0.0; 
    private static Random random = new Random(); 

    public static double BoxMuller() 
    { 
     if (uselast) 
     { 
      uselast = false; 
      return next_gaussian; 
     } 
     else 
     { 
      double v1, v2, s; 
      do 
      { 
       v1 = 2.0 * random.NextDouble() - 1.0; 
       v2 = 2.0 * random.NextDouble() - 1.0; 
       s = v1 * v1 + v2 * v2; 
      } while (s >= 1.0 || s == 0); 

      s = System.Math.Sqrt((-2.0 * System.Math.Log(s))/s); 

      next_gaussian = v2 * s; 
      uselast = true; 
      return v1 * s; 
     } 
    } 

    public static double BoxMuller(double mean, double standard_deviation) 
    { 
     return mean + BoxMuller() * standard_deviation; 
    } 

    public static int Next(int min, int max) 
    { 
     return (int)BoxMuller(min + (max - min)/2.0, 1.0); 
    } 
} 

おそらく、標準偏差を範囲に対してどのようにスケーリングする必要があるのでしょうか。理解できません。

回答:

// Will approximitely give a random gaussian integer between min and max so that min and max are at 
    // 3.5 deviations from the mean (half-way of min and max). 
    public static int Next(int min, int max) 
    { 
     double deviations = 3.5; 
     int r; 
     while ((r = (int)BoxMuller(min + (max - min)/2.0, (max - min)/2.0/deviations)) > max || r < min) 
     { 
     } 

     return r; 
    } 

答えて

6

ボックス・ミュラー法が「標準」の正規分布を返した場合、それは標準正規分布に変換するに平均0、標準偏差1を持って、あなたがして、乱数を掛けXが標準偏差Xを取得し、メモリが正しく機能する場合はYを加算して平均Yを求めます。

より正式な証明については、Wikipedia article's section on normalizing standard normal variables (property 1)を参照してください。あなたのコメントを受けて


、親指のルールは正規分布の99.7%が+/-標準偏差の3倍以内になるということです。たとえば、0から100までの正規分布が必要な場合は、平均よりも中間になり、SDは(100/2)/ 3 = 16.667になります。だから、あなたのBox-Mullerアルゴリズムからどんな値を得ても、16.667を掛けてディストリビューションを "伸ばす"ことができます。そして、50を加えて "センタリング"します。


ジョンは、あなたの最新のコメントに反応して、私は本当にNext機能のポイントが何であるかわかりません。常に標準偏差1を使用し、最小値と最大値の中間の平均値を使用します。

-X〜+ Xの範囲の〜99.7%でYの平均を求めたい場合は、BoxMuller(Y, X/3)を呼び出します。

+0

だから、この作品を修正BoxMuller(double mean、double standard_deviation)は上記のとおりです。しかし、問題は、Next(int min、int max)が範囲の半分に非常に近い値を返すことです。これは、偏差を正しくスケールする方法を理解していないためです。 –

+0

3.5標準偏差では、 "return(int)BoxMuller(min +(max - min)/ 2.0、(max - min)/ 2.0/3.5)"となります。 –

+0

標準偏差の+/- 3倍で、97%ではなく99.7%であるとコメントできますか? +/-シグマ:〜68% +/- 2sigma:〜95% +/- 3sigma:〜99.7% http://en.wikipedia.org/wiki/68-95-99.7_rule – DmitryK

1

まあ、-2 *シグマ.. +2 *シグマはベルカーブの95%を与えます。 (前述のwikiの記事の「標準偏差と信頼区間」のセクションを参照)。はい、これは何ですか

return (int)BoxMuller(min + (max - min)/2.0, 1.0); 

と(あなたが95%以上をカバーしたい場合、あるいはそれ以上)の1.0〜2.0(標準偏差)を変更

return (int)BoxMuller(min + (max - min)/2.0, 2.0); 
+0

今、私はあなたのおかげで何を公式化したいのか理解しています。私は、-2 *シグマ.. + 2 *シグマを範囲(min、max)の始めと終わりにそれぞれ設定します。 –

+0

ああ、私は今理解しています。だからあなたは平均値の左右から脱出し、95%の信頼度でminまたはmaxのいずれかを「ヒット」したいと考えています。 この場合、平均値(最小+(最大 - 最小)/ 2)を維持しますが、シグマ(標準偏差)を計算する必要があります。 2 *シグマでステップアウトすると、95%の間隔が得られます。したがって、この間隔の長さは4 *シグマです。しかし、(max-min)として計算することもできます。これは、シグマ=(最大 - 最小)/ 4を与える。 それを試してもらえますか? – DmitryK

+0

私の言葉で正確に言えば、95%信頼度でmin..maxの範囲内で「ヒット」します。 – DmitryK

関連する問題