概率模拟实验疑问:为何相对频率趋近于0?附Java代码求助
问题分析与代码修正
作业要求
本次作业需模拟hw1第5题的实验:Alice和Bob共有2𝑛+1枚公平硬币(正面概率为1/2),Bob抛掷𝑛+1枚,Alice抛掷剩余𝑛枚,证明Bob正面数多于Alice的概率为1/2。需编写程序对𝑛=5、10、50、100分别进行1000次实验,计算相对频率(公式:Bob正面数多于Alice的实验次数/总实验次数),验证其接近0.5且与𝑛无关。
随后使用偏态硬币(正面概率𝑝∈{0.2,0.3,0.4,0.6,0.7,0.8})重复实验,观察该概率是否随𝑛变化、是否存在极限值并提出猜想。
遇到的问题
编写的Java代码切换概率参数运行后,得到的相对频率始终趋近于0,原代码如下:
//1. create file //2. create file writer class //3. create print writer class File Report = new File("Report.txt"); FileWriter fw = new FileWriter(Report); PrintWriter pw = new PrintWriter(fw); Random rand = new Random(); //randomly flips head or tails int n[] = new int[4]; // number of coin flips n[0] = 5; n[1] = 10; n[2] = 50; n[3] = 100; double p = 5; //prob of 0.2, 0.3, 0.4, 0.6, 0.7, 0.8 int trials = 1000; int BHC = 0, AHC = 0; // count how many heads bob and alice flipped int c = 0; int count = 0; for(int k = 0; k < n.length; k++) { while (c < trials) { //bob: loop n+1 times for(int i = 0; i < n[k] + 1; i++) { //get randomNum btwn 0-9 int randomNum = rand.nextInt(10); //if randomNum is 0 or 1, then Bob flipped head (0.2 prob) if (randomNum < p) BHC++; } //alice: loop n times for (int j = 0; j < n[k]; j++) { //get randomNum btwn 0-9 int randomNum = rand.nextInt(10); //if randomNum is 0 or 1, then Bob flipped head (0.2 prob) if (randomNum < p) AHC++; } if (BHC > AHC) count++; c++; } double relativeFreq = (double)count/(double)trials; pw.println("The Relative Frequency when n = " + n[k] + " and p = " + p/10 + " is " + relativeFreq); } pw.close(); //close file
问题根源
实验变量未重置
BHC(Bob正面数)、AHC(Alice正面数)没有在每次单轮实验后清零,导致多轮实验的正面数持续累加,后续实验的比较逻辑完全失效。count(Bob获胜次数)、c(实验计数器)没有在每个n的循环开始前重置,导致第一个n做完1000次实验后,后续n的循环不会执行任何实验,直接复用之前的count值。
概率判断逻辑错误
- 代码中用
rand.nextInt(10)生成0-9的整数,但概率参数p被赋值为0.2、0.3这类小数,此时randomNum < p的判断永远为假(整数不可能小于0.2),导致BHC和AHC始终为0,BHC > AHC的条件永远不成立,count保持为0,相对频率自然趋近于0。
- 代码中用
修正后的代码
import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.Random; public class CoinFlipExperiment { public static void main(String[] args) { try { File report = new File("Report.txt"); FileWriter fw = new FileWriter(report); PrintWriter pw = new PrintWriter(fw); Random rand = new Random(); int[] nValues = {5, 10, 50, 100}; double[] pValues = {0.2, 0.3, 0.4, 0.6, 0.7, 0.8}; int trials = 1000; // 遍历所有概率参数 for (double p : pValues) { pw.println("=== 正面概率 p = " + p + " ==="); // 遍历所有n值 for (int n : nValues) { int winCount = 0; // 执行1000次实验 for (int trial = 0; trial < trials; trial++) { int bobHeads = 0; int aliceHeads = 0; // Bob抛n+1次 for (int i = 0; i < n + 1; i++) { if (rand.nextDouble() < p) { bobHeads++; } } // Alice抛n次 for (int i = 0; i < n; i++) { if (rand.nextDouble() < p) { aliceHeads++; } } // 判断Bob是否获胜 if (bobHeads > aliceHeads) { winCount++; } } // 计算相对频率 double relativeFreq = (double) winCount / trials; pw.printf("n = %d 时,相对频率:%.4f%n", n, relativeFreq); } pw.println(); } pw.close(); fw.close(); } catch (Exception e) { e.printStackTrace(); } } }
修正说明
- 改用
rand.nextDouble() < p直接判断正面,逻辑更直观,避免整数和小数比较的错误。 - 每个n的循环内重置
winCount,每次单轮实验内重置bobHeads和aliceHeads,保证实验独立性。 - 遍历所有指定的p值,自动完成所有参数组合的实验,无需手动修改p值。
- 添加异常处理,避免文件操作报错导致程序崩溃。
内容的提问来源于stack exchange,提问作者rysskr
相关产品推荐
相关产品推荐

