Java 蒙特卡罗模拟

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

我是一名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 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
  • 如果您在步骤2中选择了一个匹配的硬币,那么现在袋子中还剩下1个匹配的硬币。拾取的概率为
    1/4
  • 所以,得到3个垫子的概率
        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;
        }