【演算法】模擬擲骰子

Richaaaard發表於2015-06-15

模擬擲骰子。以下程式碼能夠計算每種兩個骰子之和的準確概率分佈:

int SIDES = 6;
double[] dist = new double[2*SIDES+1];
for (int i = 1; i <= SIDES; i++) 
    for (int j = 1; i <= SIDES; j++)
        dist[i+j] += 1.0;

for (int k = 2; k <= 2*SIDES; k++)
    dist[k] /= 36.0;

 dist[i] 的值就是兩個骰子之和為i的概率。用實驗模擬N次擲骰子,並在計算兩個1到

 6之間的隨機整數之和時記錄每個值的出現頻率以驗證它們的概率。N要多大才能夠保證你

 的經驗資料和準確資料的吻合程度達到小數點後三位?

實驗程式碼:

  1 package com.beyond.algs4.experiment;
  2 
  3 import java.math.BigDecimal;
  4 
  5 import com.beyond.algs4.lib.StdRandom;
  6 
  7 
  8 public class Sides {
  9 
 10     private static int SIDES = 6;
 11     
 12     private double[] dist = new double[2*SIDES + 1];
 13     
 14     public double[] getDist() {
 15         return dist;
 16     }
 17 
 18     public void setDist(double[] dist) {
 19         this.dist = dist;
 20     }
 21 
 22     public void probability() {
 23         for (int i = 1; i <= SIDES; i++) {
 24            for (int j = 1; j <= SIDES; j++) {
 25                dist[i + j] += 1.0;
 26            } 
 27         }
 28         for (int k = 2; k <= 2*SIDES; k++) {
 29             dist[k] /= 36.0;
 30         }
 31     }
 32     
 33     public void print() {
 34         for (int i = 0; i < dist.length; i++) {
 35             System.out.println(
 36                     String.format("Probability of [%d] is: %f", i, dist[i]));
 37         }
 38     }
 39     
 40     public static class Emulator {
 41         private int N = 100;
 42         
 43         private double[] dist = new double[2*SIDES + 1];
 44         
 45         public int getN() {
 46             return N;
 47         }
 48 
 49         public void setN(int n) {
 50             N = n;
 51         }
 52 
 53         public double[] getDist() {
 54             return dist;
 55         }
 56 
 57         public void setDist(double[] dist) {
 58             this.dist = dist;
 59         }
 60 
 61         public void emulator() {
 62             for (int i = 0; i < N; i++) {
 63                 int a = StdRandom.uniform(1, 7);
 64                 int b = StdRandom.uniform(1, 7);
 65                 dist[a + b] += 1.0;
 66             }
 67             for (int k = 2; k <= 2*SIDES; k++) {
 68                 dist[k] /= N;
 69             }
 70         }        
 71         
 72         public int n(Sides sides) {
 73             for (int i = 1; i <= 100; i++) {
 74                 this.setN(new Double(Math.pow(10, i)).intValue() * this.N);
 75                 this.emulator();
 76                 boolean appr = true;
 77                 for (int k = 2; k <= 2*SIDES; k++) {
 78                     double s = this.getDist()[k];
 79                     BigDecimal bs = new BigDecimal(s);
 80                     double s1 = bs.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
 81                     double t = sides.getDist()[k];
 82                     BigDecimal bt = new BigDecimal(t);
 83                     double t1 = bt.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
 84                     if (s1 != t1) {
 85                         appr = false;
 86                         break;
 87                     }
 88                 }
 89                 if (appr) {
 90                     return this.getN();   
 91                 }
 92             }
 93             return 0;
 94         }
 95         
 96         public void print() {
 97             for (int i = 0; i < dist.length; i++) {
 98                 System.out.println(
 99                         String.format("Probability of [%d] is: %f", i, dist[i]));
100             }
101         }
102         
103         
104     }
105     
106     public static void main(String[] args) {
107         Sides sides = new Sides();
108         sides.probability();
109 
110         Emulator e = new Emulator();
111         int N = e.n(sides);
112         System.out.println(String.format("The N is: %d", N));
113         System.out.println("Actual: ");
114         sides.print();
115         System.out.println("Experiment: ");
116         e.print();
117     }
118 
119 }


實驗結果:

 1 The N is: 100000000
 2 Actual: 
 3 Probability of [0] is: 0.000000
 4 Probability of [1] is: 0.000000
 5 Probability of [2] is: 0.027778
 6 Probability of [3] is: 0.055556
 7 Probability of [4] is: 0.083333
 8 Probability of [5] is: 0.111111
 9 Probability of [6] is: 0.138889
10 Probability of [7] is: 0.166667
11 Probability of [8] is: 0.138889
12 Probability of [9] is: 0.111111
13 Probability of [10] is: 0.083333
14 Probability of [11] is: 0.055556
15 Probability of [12] is: 0.027778
16 Experiment: 
17 Probability of [0] is: 0.000000
18 Probability of [1] is: 0.000000
19 Probability of [2] is: 0.027754
20 Probability of [3] is: 0.055544
21 Probability of [4] is: 0.083374
22 Probability of [5] is: 0.111130
23 Probability of [6] is: 0.138897
24 Probability of [7] is: 0.166751
25 Probability of [8] is: 0.138832
26 Probability of [9] is: 0.111088
27 Probability of [10] is: 0.083306
28 Probability of [11] is: 0.055517
29 Probability of [12] is: 0.027807

 

結果分析:
多次執行,N值一般為100000000,也有不穩定的時候是其他數值。

 

補充說明:

1. 以N=100為初始值,迴圈執行計算模擬N次的概率情況,如果吻合度不滿足則N以10倍遞增直至找到合適的N值。(有待改進,採用while(find))

2. “吻合程度達到小數點後三位”的實現方式採用小數點後三位ROUND_DOWN的方式,有待改進

3. N值並非每次執行皆為100000000的穩定結果,可適當隨機多次執行,以分析N值的分佈情況

 

參考資料:

演算法 第四版  謝路雲 譯 Algorithms Fourth Edition [美] Robert Sedgewick, Kevin Wayne著

http://algs4.cs.princeton.edu/home/

原始碼下載連結:

http://pan.baidu.com/s/1c0jO8DU

相關文章