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