- ビュフォンの針を使った円周率の計算機推定の話題(こちら)がある。
- 簡単に言うと、等長の針を、針の長さより長い幅の縞模様の上に投げて、針が1つの縞に納まるか、2つの縞に跨るかの割合から円周率が推定できるという話です。
- (1)針の頭の位置を一様乱数で発生し、針の向き(角度)を0-2πの一様乱数で発生させれば、針の位置は決まりますから、シミュレーションは成功です。ですが、針の向きの一様乱数発生に円周率を使っているので、これは「ずる」です。
L <- 5/6
n <- 10^4
head.x <- runif(n)
head.y <- runif(n)
theta <- runif(n)*2*pi
tail.x <- head.x + L*cos(theta)
fl.head <- floor(head.x)
fl.tail <- floor(tail.x)
check <- fl.head==fl.tail
table(check)
2 * L * n / (n-sum(check))
- 別の方法。針の頭の位置を基準として、針先の相対位置が決まればよいのです。それは、単位円周上の一様分布が発生できればよいです。方向に関して一様な分布がランダムに作れれば、それを単位半径に縮めさえすればよいので、結局、方向一様な2次元分布を原点を中心に作れればよいことがわかります。x,yの両方に正規乱数を与えると2次元正規分布の乱点が作れます。
needle <- cbind(rnorm(n),rnorm(n))
plot(needle)
r <- sqrt(needle[,1]^2+needle[,2]^2)
needle.1 <- cbind(needle[,1]/r,needle[,2]/r)
plot(needle.1)
tail.x <- head.x + L * needle.1[,1]
fl.head <- floor(head.x)
fl.tail <- floor(tail.x)
check <- fl.head==fl.tail
table(check)
2 * L * n / (n-sum(check))
- (3)正規乱数を作る、とは言っても、正規分布の関数表現には、指数関数やpiが現れますから、これも「ずる」な感じです。方向一様な2次元分布を作ればよいので、[-1,1] x [-1,1]という正方形に一様乱数を発生させ、そのうち、半径1以下の点だけを取れば、単位円板上の一様乱点が得られますので、これを単位円周に移動させればよいですね。
X <- runif(n,min=-1,max=1)
Y <- runif(n,min=-1,max=1)
plot(X,Y)
R <- sqrt(X^2+Y^2)
ok <- which(R<=1)
X.ok <- X[ok]
Y.ok <- Y[ok]
plot(X.ok,Y.ok)
needle <- cbind(X.ok,Y.ok)
r <- sqrt(needle[,1]^2+needle[,2]^2)
needle.1 <- cbind(needle[,1]/r,needle[,2]/r)
plot(needle.1)
tail.x <- head.x + L * needle.1[,1]
fl.head <- floor(head.x)
fl.tail <- floor(tail.x)
check <- fl.head==fl.tail
table(check)
2 * L * n / (n-sum(check))