编程语言
首页 > 编程语言> > java – Bertrand的悖论模拟

java – Bertrand的悖论模拟

作者:互联网

所以,我前几天在Hacker News上看到了这个:http://web.mit.edu/tee/www/bertrand/problem.html

它基本上表示半径为1的圆上的随机和弦的长度大于3的平方根的概率是多少.

看看它,答案显然是1/3,但对HN的评论让人比我更聪明. https://news.ycombinator.com/item?id=10000926

我不想辩论,但我确实想确保我不是疯了.所以我编码了我认为会证明它是P = 1/3,但我最终得到P~.36.所以,我的代码有些不对劲.

我可以进行健全检查吗?

    package com.jonas.betrand;

    import java.awt.geom.Point2D;
    import java.util.Random;

    public class Paradox {
        final static double ROOT_THREE = Math.sqrt(3);

        public static void main(String[] args) {
            int greater = 0;
            int less = 0;
            for (int i = 0; i < 1000000; i++) {
                Point2D.Double a = getRandomPoint();
                Point2D.Double b = getRandomPoint();

                //pythagorean
                if (Math.sqrt(Math.pow((a.x - b.x), 2) + Math.pow((a.y - b.y), 2)) > ROOT_THREE) {
                    greater++;
                } else {
                    less++;
                }   
            }
            System.out.println("Probability Observerd: " + (double)greater/(greater+less));
        }

        public static Point2D.Double getRandomPoint() {
            //get an x such that -1 < x < 1
            double x = Math.random();
            boolean xsign = new Random().nextBoolean();
            if (!xsign) {
                x *= -1;
            }

            //formula for a circle centered on origin with radius 1: x^2 + y^2 = 1
            double y = Math.sqrt(1 - (Math.pow(x, 2)));
            boolean ysign = new Random().nextBoolean();
            if (!ysign) {
                y *= -1;
            }

            Point2D.Double point = new Point2D.Double(x, y);
            return point;
        }
    }

编辑:感谢一群人让我直截了当,我发现我找到随机点的方法并不是那么随意.这是该函数的修复,返回约1/3.

        public static Point2D.Double getRandomPoint() {
            //get an x such that -1 < x < 1
            double x = Math.random();
            Random r = new Random();
            if (!r.nextBoolean()) {
                x *= -1;
            }

            //circle centered on origin: x^2 + y^2 = r^2. r is 1. 
            double y = Math.sqrt(1 - (Math.pow(x, 2)));
            if (!r.nextBoolean()) {
                y *= -1;
            }

            if (r.nextBoolean()) {
                return new Point2D.Double(x, y);
            } else {
                return new Point2D.Double(y, x);
            }
        }

解决方法:

我相信你需要假设一个固定点说(0,1),然后在圆周围的[0,2 * pi]中选择一个随机的旋转量,用于和弦的第二个点的位置.

只是为了它的地狱我在Swift中写了你不正确的版本(学习Swift!):

    struct P {
        let x, y: Double
        init() {
            x = (Double(arc4random()) / 0xFFFFFFFF) * 2 - 1
            y = sqrt(1 - x * x) * (arc4random() % 2 == 0 ? 1 : -1)
        }
        func dist(other: P) -> Double {
            return sqrt((x - other.x) * (x - other.x) + (y - other.y) * (y - other.y))
        }
    }
    let root3 = sqrt(3.0)
    let total = 100_000_000
    var samples = 0
    for var i = 0; i < total; i++ {
        if P().dist(P()) > root3 {
            samples++
        }
    }
    println(Double(samples) / Double(total))

答案确实是0.36.正如评论所解释的那样,随机X值更可能选择pi / 2附近的“扁平区域”,并且极不可能选择0和pi附近的“垂直挤压”区域.

但是在P的构造函数中很容易修复:
(Double(arc4random())/ 0xFFFFFFFF对于[0,1)中的随机浮点数来说很花哨

        let angle = Double(arc4random()) / 0xFFFFFFFF * M_PI * 2
        x = cos(angle)
        y = sin(angle)
        // outputs 0.33334509

标签:java,simulation,paradox
来源: https://codeday.me/bug/20190823/1694985.html