【算法】模拟掷骰子

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

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

时间: 2024-10-09 01:25:07

【算法】模拟掷骰子的相关文章

模拟算法_掷骰子游戏&amp;&amp;猜数游戏

模拟算法是用随机函数来模拟自然界中发生的不可预测的情况,C语言中是用srand()和rand()函数来生成随机数. 先来介绍一下随机数的生成: 1.产生不定范围的随机数 函数原型:int rand() 产生一个介于0~RAD_MAX间的整数,其具体值与系统有关系.Linux下为2147483647.我们可以在include文件夹中的stdlib.h中可以看到(Linux在usr目录下,Windows在安装目录下) 1 #include<stdio.h> 2 #include<stdlib

使用Pygal模拟掷骰子

在本节中,将使用Python可视化包Pygal来生成可缩放的矢量图形文件. 对于需要在尺寸不同的屏幕上显示的图表,这很有用,因为它们将自动缩放,以适合观看者的屏幕. 1.创建Die类 from random import randint class Die(): def __init__(self,num_sides=6): self.num_sides=num_sides def roll(self): return randint(1,self.num_sides) 2.分析1000次结果

LeetCode 1223. 掷骰子模拟 Dice Roll Simulation - Java - DP

题目链接:1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现在,给你一个整数数组 rollMax 和一个整数 n,请你来计算掷 n 次骰子可得到的不同点数序列的数量. 假如两个序列中至少存在一个元素不同,就认为这两个序列是不同的.由于答案可能很大,所以请返回 模 \(10^9 + 7\) 之后的结果. 示例1: 输入:n =

上帝掷骰子吗? 计算机程序构造解释 奇思妙想-摘要

书籍部分概要 上帝掷骰子吗-量子物理史话 假如一个物理概念是无法测量的,它就是没有意义的.对于这个物我合一的世界来说,任何东西都应该是可以测量和感知的.只有可观测的量才是存在的!(不完全性定理,海森堡不确定性原理 低维世界无法感知高维世界,即解释高维世界.或者我相信原子是四维的或者是多维的总之是高于三维世界存在的,所以表现出波力二象性 .)二维度的语言无法描述高维信息,因此语言或表述方法决定了我们能看的多远. 理论决定了我们能够观察什么,(即同样的心智模式.一个人的认知决定了 他能观察到什么事物

掷骰子问题之C语言随机数

之前有看到有人在写“掷骰子100次,打印出掷骰子”的代码 便找空写了一下代码,不是很好,仅供大家讨论 因为掷骰子的结果是在1~6之间随机产生的,因此代码也必须要模拟随机的情况 但是电脑是无法真正的产生随机数,只能以函数近似生成的方式得到,因此我的代码也是基于这种方式写出的 得到随机数的方式有两步,第一步是设置产生随机数的种子,第二步才是根据种子得到随机数 这两步分别对应了两个函数:srand()和rand() 并且由于是函数生成,函数的特性决定了如果种子一样,会得到相同的结果,也就不存在随机的情

Algs4-1.1.35模拟投骰子

1.1.35模拟投骰子.以下代码能够计算每两个骰子之和的准确概率分布:public class Test{    public static void main(String[] args)    {        int SIDES=6;        double[] dist=new double[2*SIDES+1];        for (int i=1;i<=SIDES;i++)            for (int j=1;j<=SIDES;j++)             

华为历年试题(掷骰子游戏 7)

问题描述: 在掷骰子游戏中,会根据所掷数字在地图中前进几步,前进完成后需要根据当前地图位置所示的障碍进行相应操作,其中障碍表示: 1)  9:无障碍 2)  1:停掷一轮,即下轮所掷数字无效: 3)  2:后退两步,如果已经到起点不再后退: 4)  3:奖励前进一步 如果在游戏过程中,已经走到地图终点,则游戏结束.根据输入的地图数组,和5个骰子数的数组,返回最终玩家前进了多少步. 要求实现函数: void dice(int map_len, int* map, int* dice_val, in

第21本:《上帝掷骰子吗?》

第21本:<上帝掷骰子吗?> 这是一本关于量子论的科普读物,不过作者曹天元把一系列人物和实验用一种小说的形式讲 述了下来,很感叹作者深厚的理论知识和文字功底.这本书在豆瓣上评分在9.3-9.4,我的GTD阅读清单是按照评分顺序来整理的,超过9分的读物如果不 优先阅读真有点对不起书名里的上帝. 这类书既然是科普知识类的书,就很难找到可以执行的行动,这些知识体系能让你的视野开阔,当思考一个问题时不能被其表面现象所迷惑,任何一个定律都 不是绝对适用的.在读到能量不是连续的,而是一份一份的,再想到计算

骑士飞行棋第一版(掷骰子方法分开)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 骑士飞行棋 8 { 9 class Program 10 { 11 12 //在下面的数组存储我们游戏地图各个关卡 13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格...下标为n的元素对应n+1