Java 蒙特卡罗模拟
我是一名Java编程课程的学生。我的问题是关于蒙特卡罗模拟的解释。我应该找到从一个有3个25美分和3个便士的钱包中取出3个25美分或3个便士的概率。硬币一旦被拣走,就不会被替换。概率应为0.1xxxxxx。我的答案一直是0或1。这就是我目前所拥有的Java 蒙特卡罗模拟,java,simulation,probability,montecarlo,Java,Simulation,Probability,Montecarlo,我是一名Java编程课程的学生。我的问题是关于蒙特卡罗模拟的解释。我应该找到从一个有3个25美分和3个便士的钱包中取出3个25美分或3个便士的概率。硬币一旦被拣走,就不会被替换。概率应为0.1xxxxxx。我的答案一直是0或1。这就是我目前所拥有的 public class CoinPurse { public static void main(String[] args) { System.out.print("Probability of Drawing 3 coin
public class CoinPurse {
public static void main(String[] args) {
System.out.print("Probability of Drawing 3 coins of the Same Type - ");
System.out.println(coinPurseSimulation(100));
}
/**
Runs numTrials trials of a Monte Carlo simulation of drawing
3 coins out of a purse containing 3 pennies and 3 quarters.
Coins are not replaced once drawn.
@param numTrials - the number of times the method will attempt to draw 3 coins
@returns a double - the fraction of times 3 coins of the same type were drawn.
*/
public static double coinPurseSimulation(int numTrials) {
final int P = 1;
final int Q = 2;
int [] purse = {Q, Q, Q, P, P, P};
int [] drawCoins = new int[3];
for (int draw = 0; draw < 3; draw ++) {
int index = (int)(Math.random() * purse.length);
drawCoins[draw] = purse[index];
int [] newPurse = new int[purse.length-1];
int j = 0;
for (int i =0; i < purse.length; i++) {
if (i == index) {
continue;
}
newPurse[j] = purse[i];
j++;
}
purse = newPurse;
}
double number = 0.0;
double result = 0.0;
for (int i = 0; i < numTrials; i++) {
result++;
for (int j = 0; j < numTrials;j++) {
if(drawCoins[0] == drawCoins [1] && drawCoins[1] == drawCoins[2]) {
number++;
}
}
}
return number/result;
}
}
公共类{
公共静态void main(字符串[]args){
系统输出打印(“抽取3枚相同类型硬币的概率-”;
系统输出println(coinPurseSimulation(100));
}
/**
运行绘图的蒙特卡罗模拟的数值试验
从一个钱包里拿出3枚硬币,里面装着3个便士和3个25美分硬币。
硬币一经提取就不会被替换。
@param numTrials-该方法尝试抽取3枚硬币的次数
@返回一个双精度值-抽取3枚相同类型硬币的分数。
*/
公共静态双精度模拟(整数){
最终INTP=1;
最终int Q=2;
int[]钱包={Q,Q,Q,P,P,P};
整数[]抽取硬币=新整数[3];
用于(int-draw=0;draw<3;draw++){
int索引=(int)(Math.random()*钱包长度);
提取硬币[提取]=钱包[索引];
int[]新钱包=新的int[钱包长度-1];
int j=0;
对于(int i=0;i<1.length;i++){
如果(i==索引){
继续;
}
新钱包[j]=钱包[i];
j++;
}
钱包=新钱包;
}
双倍数=0.0;
双结果=0.0;
对于(int i=0;i
您需要将生成绘图的循环向下移动到numTrials
循环中。按照您编写的方式,您正在绘制一张图,然后检查一个结果numTrials
次
我没有仔细检查你画图的逻辑,但那是因为我建议使用一种不同的(而且更简单)方法。在你的硬币和硬币上使用,并在每次洗牌后检查前三个元素
如果操作正确,答案应该是
2*(3/6)*(2/5)*(1/4)
,即0.1。您需要将生成绘图的循环向下移动到numTrials
循环中。按照您编写的方式,您正在绘制一张图,然后检查一个结果numTrials
次
我没有仔细检查你画图的逻辑,但那是因为我建议使用一种不同的(而且更简单)方法。在你的硬币和硬币上使用,并在每次洗牌后检查前三个元素
如果做得正确,答案应该是
2*(3/6)*(2/5)*(1/4)
,即0.1。你只会得到0
或1
的原因是你只会从钱包中抽取(或拾取)一次硬币,但你会测试抽取numTrials*numTrials
次。您有两个循环(索引为i
和j
)迭代numTrials
时间-您的逻辑有点混乱
您可以将第一个循环(用于提取硬币)放在第二个循环(用于运行测试)中,您的代码将正常工作。我在下面列出了一个最小的重构(尽可能使用您的代码),后面有两条注释可能会对您有所帮助
public class CoinPurse
{
public static void main(String[] args)
{
System.out.print("Probability of Drawing 3 coins of the Same Type - ");
System.out.println(coinPurseSimulation(100));
}
/**
* Runs numTrials trials of a Monte Carlo simulation of drawing 3 coins out
* of a purse containing 3 pennies and 3 quarters. Coins are not replaced
* once drawn.
*
* @param numTrials
* - the number of times the method will attempt to draw 3 coins
* @returns a double - the fraction of times 3 coins of the same type were
* drawn.
*/
public static double coinPurseSimulation(int numTrials)
{
final int P = 1;
final int Q = 2;
double number = 0.0;
double result = 0.0;
// Changed your loop index to t to avoid conflict with i in your draw
// loop
for (int t = 0; t < numTrials; t++)
{
result++;
// Moved your draw without replacement code here
int[] purse =
{ Q, Q, Q, P, P, P };
int[] drawCoins = new int[3];
for (int draw = 0; draw < 3; draw++)
{
int index = (int) (Math.random() * purse.length);
drawCoins[draw] = purse[index];
int[] newPurse = new int[purse.length - 1];
int j = 0;
for (int i = 0; i < purse.length; i++)
{
if (i == index)
{
continue;
}
newPurse[j] = purse[i];
j++;
}
purse = newPurse;
}
// Deleted the loop with index j - you don't need to test the same
// combination numTrials times...
if (drawCoins[0] == drawCoins[1] && drawCoins[1] == drawCoins[2])
{
number++;
}
}
return number / result;
}
}
现在,您只需从第二个循环中调用即可
drawCoins = pickCoins(purse, 3);
采样算法
建议使用Collections.shuffle()
,然后取出收藏中的前3枚硬币(例如,一枚硬币)。这是一个很好的建议,但我猜您还没有被介绍到集合
,可能不被“允许”使用它们。如果你是,一定要使用它们。如果不是(我假设),您可能想考虑更好的方法,从一个r长度数组中随机抽取n个项,而不进行替换
一种(被广泛接受的)方式是货币及其衍生工具。实际上,它涉及从数组的未拾取的子集中随机拾取
在Java中,一个可行的例子如下:它将拾取的硬币移动到钱包的“末端”,只从第一个maxInd
未拾取的硬币中拾取
private static int[] pickCoins(int[] purse, int numCoins)
{
int[] samples = new int[numCoins];
int maxInd = purse.length - 1;
for (int i = 0; i < numCoins; i++)
{
int index = (int) (Math.random() * maxInd);
int draw = purse[index];
samples[i] = draw;
// swap the already drawn sample with the one at maxInd and decrement maxInd
purse[index] = purse[maxInd];
purse[maxInd] = draw;
maxInd -= 1;
}
return samples;
}
private static int[]pickCoins(int[]钱包,int numCoins)
{
int[]样本=新的int[numCoins];
int maxInd=钱包长度-1;
for(int i=0;i
预期结果
您说您的预期结果是0.1xxxxxx
。在学习蒙特卡罗模拟时,您可能需要进一步考虑这一点。预期结果取决于你做了多少次试验
首先,在这个简单的例子中,你可以考虑分析(或者在某种意义上<强>精确< /强>)结果。考虑程序:
2/5
1/4
private static int[] pickCoins(int[] purse, int numCoins)
{
int[] samples = new int[numCoins];
int maxInd = purse.length - 1;
for (int i = 0; i < numCoins; i++)
{
int index = (int) (Math.random() * maxInd);
int draw = purse[index];
samples[i] = draw;
// swap the already drawn sample with the one at maxInd and decrement maxInd
purse[index] = purse[maxInd];
purse[maxInd] = draw;
maxInd -= 1;
}
return samples;
}