標籤:
類比擲骰子。以下代碼能夠計算每種兩個骰子之和的準確機率分布:
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.13888910 Probability of [7] is: 0.16666711 Probability of [8] is: 0.13888912 Probability of [9] is: 0.11111113 Probability of [10] is: 0.08333314 Probability of [11] is: 0.05555615 Probability of [12] is: 0.02777816 Experiment: 17 Probability of [0] is: 0.00000018 Probability of [1] is: 0.00000019 Probability of [2] is: 0.02775420 Probability of [3] is: 0.05554421 Probability of [4] is: 0.08337422 Probability of [5] is: 0.11113023 Probability of [6] is: 0.13889724 Probability of [7] is: 0.16675125 Probability of [8] is: 0.13883226 Probability of [9] is: 0.11108827 Probability of [10] is: 0.08330628 Probability of [11] is: 0.05551729 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
【演算法】類比擲骰子