---恢复内容开始---
习题:1.1.35
以下代码能够计算每种两个骰子之和的准确概率分布:
int SIDES = 6;
double[] dist = new double[2 * SIDES + 1];
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;
dist[i] 的值就是两个骰子之和为i的概率。用实验模拟N次掷骰子,并在计算两个1到 6之间的随机整数之和时记录每个值的出现频率以验证它们的概率。N要多大才能够保证你的经验数据和准确数据的吻合程度达到小数点后三位?
一、实验思路分析:
1.计算掷两枚骰子所得点数之和的准确概率;
2.计算模拟掷N次所得两枚骰子点数之和的经验概率;
3.当经验概率与准确概率吻合到小数点后三位时输出数据。
二、实验解释:
关于存放概率的数组长度,骰子有六面,掷两枚可以依次掷出总和为2,3,4,5,6,7,8,9,10,11,12等一共11种结果,数组下标从0 开始标记,所以数组的长度在声明时需要声明成11+2 = 62+1 =SIDES2+1一共13的长度;
换个更简单的思路可以这么想,物理情况下总和最低是1+1=2,最高是6+6=12,存放12本质上是数据的第13个数据,因此声明长度为13的数组; 不用考虑具体的某一种情况的总和,因为i+j总和可以出现的情况是有穷的
既然和的情况是有穷的,那么移植到模拟实验的部分,每次随机出来的两个数字m n,也就可以使用m+n将得到的和次数填充到数组里;
反复对比,N*=2直到全部情况数据经验概率与准确概率吻合到小数点后三位时输出,其中p是用来控制循环的变量,当两种概率的吻合度并没有达到小数点后三位时,p始终置为0保证循环继续使N增大,N增大物理意义上就使得模拟掷骰子的次数上升了;直到全部情况的吻合度达到要求,跳出循环。
三、实验代码:
package Chapter1_1;
import java.util.Arrays;
import java.util.Scanner;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdRandom;
public class Ex35 {
//准确数据的概率
public static double[] dice() {
int SIDES=6;
double[] dist=new double[2*SIDES+1];
for(int i=1;i<=SIDES;i++) {
for(int j=1;j<=SIDES;j++) {
dist[i+j]+=1;
}
}
for(int k=2;k<=2*SIDES;k++) {
dist[k]/=36.0;
}
return dist;
}
//计算模拟掷N次所得两枚骰子点数之和的经验概率
public static double[] testDice(double N){
int SIDES = 6;
double[] a = new double[2*SIDES+1];
double t = N;
while(N>0){
int m = 1+(StdRandom.uniform(6));
int n = 1+(StdRandom.uniform(6));
a[m+n] += 1.0;
N--;
}
for(int i=2;i<=SIDES*2;i++){
a[i] /= t;
}
return a;
}
public static void main(String[] args) {
int SIDES=6;
double N=64;
boolean flag=true;
double[] b=dice();
System.out.println("准确数据的概率");
for(int i=0;i<b.length;i++) {
System.out.println(b[i]);
}
System.out.println();
double[] c=new double[2*SIDES+1];
int p=0;
while(flag) {
//p=1;
flag=false;
c=testDice(N);
for(int i=2;i<=2*SIDES;i++) {
if(Math.abs(b[i]-c[i])>0.0001) {
flag=true;
//p=0;
//flag=false;
// System.out.println("不符合题意要求,请重新输入一个更大的N值!");
break;
}
}
N*=2;
}
System.out.println("两骰和"+" "+"准确数据"+" "+"实验数据"+"所求N的值为:"+N);
for(int i=0;i<=2*SIDES;i++) {
System.out.println(i+" "+b[i]+" "+c[i]);
}
}
}
四、实验结果截图:
结果1:
结果2: