蒙特卡洛蒲丰投针方法验证圆周率

185 阅读1分钟

蒙特卡洛蒲丰投针方法(宋浩老师概率课堂www.bilibili.com/video/BV1ot… ) 验证π值,

100000000投掷,验证结果 π=3.1414777872781303

public class MonteCarloToPi {

    /**
     * 平行线距离
     */
    private static final double D = 10.0;
    /**
     * 针的长度
     */
    private static final double L = 6.0;

    @Test
    public void throwNeedleToPI() {
        int SAMPLE_COUNT = 100000000;
        int currentSampleCount = 0;
        int matchCount = 0;

        while (true) {
            currentSampleCount = currentSampleCount + 1;
            if (currentSampleCount > SAMPLE_COUNT) {
                break;
            }
            double angle = randomDouble(180.0);
            double anglePI = angle * Math.PI / 180;

            double x = randomDouble(D / 2);
            double xRange = L / 2 * Math.sin(anglePI);
            if (x > xRange) {
                continue;
            }
            double value = x / Math.sin(anglePI);
            double targetValue = L / 2;
            if (value <= targetValue) {
                matchCount++;
            }
        }
        System.out.println(String.format("currentSampleCount: %s, matchCount:%s", currentSampleCount, matchCount));
        System.out.println(String.format("π=%s", 2 * L * SAMPLE_COUNT / (matchCount * D)));
    }

    /**
     * 生成随机数,在value范围
     * @param value
     * @return
     */
    double randomDouble(double value) {
        double multi = 1000000000000000.0;
        double multiValue = value * multi;
        long longValue = BigDecimal.valueOf(multiValue).longValue();
        long random = 0;
        while (true) {
            random = Math.abs(RandomUtils.nextLong());
            if (random <= longValue) {
                break;
            }
        }
        return random / multi;
    }
}