1

这个简单的程序程序通过模拟飞镖投掷到正方形上来计算 pi 的估计值。

Сonditions:生成一个随机浮点数并将其转换为介于 -1 和 1 之间。
存储在 x 中。对 y 重复。检查 (x, y) 在单位圆内,即 (0, 0) 和 (x, y) 之间的距离 <= 1。

在此之后,需要找到ratio hits / tries与比率大致相同的circle area / square area = pi / 4。(正方形是每 1 个)。

代码:

public class MonteCarlo {
    public static void main(String[] args) 
    {
        System.out.println("Number of tries");
        Random generator = new Random(42);
        Scanner in = new Scanner(System.in);
        int tries = in.nextInt();

        int hits = 0;
        double x, y;
        for (int i = 1; i <= tries; i++)
        {
            // Generate two random numbers between -1 and 1            
            int plusOrMinus = generator.nextInt(1000);
            if (plusOrMinus > 500) x = generator.nextDouble();                
            else x = -generator.nextDouble();

            plusOrMinus = generator.nextInt(10000);
            if (plusOrMinus > 5000) y = generator.nextDouble(); 
            else y = -generator.nextDouble();             

            if (Math.sqrt((x * x) + (y * y)) <= 1) // Check whether the point lies in the unit circle
            {
                hits++;
            }
        }

        double piEstimate = 4.0 * hits / tries;
        System.out.println("Estimate for pi: " + piEstimate);
    }
}

测试输出:

  Actual output            Expected output
  -----------------------------------------------
  Number of tries          Number of tries
  1000                     1000
- Estimate for pi: 3.176   Estimate for pi: 3.312

  Actual output               Expected output
  -----------------------------------------------------
  Number of tries             Number of tries
  1000000                     1000000
- Estimate for pi: 3.141912   Estimate for pi: 3.143472

也许,是否存在其他方法来找到这个解决方案?有什么建议么。

4

2 回答 2

6

要生成介于 -1 和 1 之间的随机双精度,请尝试:

generator.nextDouble() * 2 - 1

顺便说一句:如果您继续使用静态种子初始化随机数,您将始终得到相同的结果。否则,如果您担心您的结果不够好,请记住蒙特卡洛只是一个近似值。毕竟,它是基于随机数的,所以结果与示例解决方案有所不同;-)

于 2013-07-03T08:57:33.303 回答
1

将 Uniform(0,1) 转换为 Uniform(a,b)(其中 a < b)的通用解决方案是

(b - a) * generator.nextDouble() + a

正如@winSharp93 指出的那样,您应该期待变化,但您可以将误差幅度量化为统计置信区间。如果你计算

halfWidth = 1.96 * Math.sqrt(piEstimate * (4.0 - piEstimate) / tries);

那么 pi 的实际值应该在95%piEstimate - halfWidth之间。piEstimate + halfWidth从计算中可以看出,halfWidth包含 pi 的范围会随着数量的tries增加而缩小(但不是线性地)。您可以将置信水平从 95% 调整为其他值,方法是将 1.96 替换为标准正态表中的替代比例值。

于 2013-07-03T17:13:37.093 回答