您的位置:首页 > 其它

【算法】模拟掷骰子

2015-06-15 12:02 363 查看
模拟掷骰子。以下代码能够计算每种两个骰子之和的准确概率分布:

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要多大才能够保证你

的经验数据和准确数据的吻合程度达到小数点后三位?

实验代码:

package com.beyond.algs4.experiment;

import java.math.BigDecimal;

import com.beyond.algs4.lib.StdRandom;

public class Sides {

private static int SIDES = 6;

private double[] dist = new double[2*SIDES + 1];

public double[] getDist() {
return dist;
}

public void setDist(double[] dist) {
this.dist = dist;
}

public void probability() {
for (int i = 1; i <= SIDES; i++) {
for (int j = 1; j <= SIDES; j++) {
dist[i + j] += 1.0;
}
}
for (int k = 2; k <= 2*SIDES; k++) {
dist[k] /= 36.0;
}
}

public void print() {
for (int i = 0; i < dist.length; i++) {
System.out.println(
String.format("Probability of [%d] is: %f", i, dist[i]));
}
}

public static class Emulator {
private int N = 100;

private double[] dist = new double[2*SIDES + 1];

public int getN() {
return N;
}

public void setN(int n) {
N = n;
}

public double[] getDist() {
return dist;
}

public void setDist(double[] dist) {
this.dist = dist;
}

public void emulator() {
for (int i = 0; i < N; i++) {
int a = StdRandom.uniform(1, 7);
int b = StdRandom.uniform(1, 7);
dist[a + b] += 1.0;
}
for (int k = 2; k <= 2*SIDES; k++) {
dist[k] /= N;
}
}

public int n(Sides sides) {
for (int i = 1; i <= 100; i++) {
this.setN(new Double(Math.pow(10, i)).intValue() * this.N);
this.emulator();
boolean appr = true;
for (int k = 2; k <= 2*SIDES; k++) {
double s = this.getDist()[k];
BigDecimal bs = new BigDecimal(s);
double s1 = bs.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
double t = sides.getDist()[k];
BigDecimal bt = new BigDecimal(t);
double t1 = bt.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
if (s1 != t1) {
appr = false;
break;
}
}
if (appr) {
return this.getN();
}
}
return 0;
}

public void print() {
for (int i = 0; i < dist.length; i++) {
System.out.println(
String.format("Probability of [%d] is: %f", i, dist[i]));
}
}

}

public static void main(String[] args) {
Sides sides = new Sides();
sides.probability();

Emulator e = new Emulator();
int N = e.n(sides);
System.out.println(String.format("The N is: %d", N));
System.out.println("Actual: ");
sides.print();
System.out.println("Experiment: ");
e.print();
}

}


实验结果:

The N is: 100000000
Actual:
Probability of [0] is: 0.000000
Probability of [1] is: 0.000000
Probability of [2] is: 0.027778
Probability of [3] is: 0.055556
Probability of [4] is: 0.083333
Probability of [5] is: 0.111111
Probability of [6] is: 0.138889
Probability of [7] is: 0.166667
Probability of [8] is: 0.138889
Probability of [9] is: 0.111111
Probability of [10] is: 0.083333
Probability of [11] is: 0.055556
Probability of [12] is: 0.027778
Experiment:
Probability of [0] is: 0.000000
Probability of [1] is: 0.000000
Probability of [2] is: 0.027754
Probability of [3] is: 0.055544
Probability of [4] is: 0.083374
Probability of [5] is: 0.111130
Probability of [6] is: 0.138897
Probability of [7] is: 0.166751
Probability of [8] is: 0.138832
Probability of [9] is: 0.111088
Probability of [10] is: 0.083306
Probability of [11] is: 0.055517
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: