【算法】模拟掷骰子

模拟掷骰子。以下代码能够计算每种两个骰子之和的准确概率分布:

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

原文地址:https://www.cnblogs.com/richaaaard/p/4576787.html