Here's my code
buffon <- function(a,l)
{
n<-0
N<-0
repeat {N<-N+1
print(N)
p<-c(n/N)
# Sample the location of the needle's centre.
x<-runif(1,min = 0,max =a/2)
print(x)
# Sample angle of needle with respect to lines.
theta<-runif(1, 0, pi/2)
print(theta)
# Does the needle cross a line?
k<-l/2*sin(theta)
ifelse(x<=k,n<-n+1,n<-n)
p<-c(n/N)
print(p)
pie<-(2*l)/(p*a)
print(pie)
if(N>5000) {break}
}
}
I am trying to estimate the value of pi using the idea of Buffon's needle, however, when I try:buffon(2,3)
, the final estimation is 3.8, which is far greater than 3.1. Could someone explain to me if there's any mistakes in my code or I cannot use pi to estimate pi?
Addition:
I realized that many lines of my code are redundant so I modified it a bit this morning:
buffon01 <- function(n,a,l)
{
# Sample the location of the needle's centre.
x<-runif(n,min = 0,max =a/2)
# Sample angle of needle with respect to lines.
theta<-runif(n, 0, pi/2)
# Does the needle cross a line?
k<-l/2*sin(theta)
# l is the length of the needle
# a is the distance between to parallel line
v<-length(x[x<=k])
p<-c(v/n)
pie<-(2*l)/(p*a)
list("pi"=pie,"error"=abs(pie-pi))
}
By setting a way larger than l I am able to get a fairly close result to 3.14... but the result I get is very unstable... as in if I do the same experiment again 3.1* could be any number other than 4... Did I ignore some other problems in my setting?
As far as I can tell. Your problem is that you are using a "long" needle (where l > a), and then the formula l/2*cos(theta)
does not work. In that case, you need to use the slightly more elaborate formula.
So I have cleaned your code a bit, and modified ensure that l < a:
buffon <- function(a,l) {
stopifnot(l < a)
n<-0
N<-0
repeat {
N <- N+1
# Sample the location of the needle's centre.
x <- runif(1, min=0, max=a/2)
# Sample angle of needle with respect to lines.
theta <- runif(1, min=0, max=pi/2)
# Does the needle cross a line?
n <- ifelse(x <= l/2*cos(theta), n + 1, n)
# Estimate probability of crossing line
p <- n/N
# Compute pi
pie <- (2*l)/(p*a)
if (N>50000) { # Note the increased iterations
break
}
}
return(pie)
}
ans <- buffon(a=3,l=2)
print(ans)
#[1] 3.159621
I appears you have also switched cos
with sin
in the stated formula for checking if the needle hits a line. However---off the top of my head---that does not matter. Lastly, printing inside the "repeat"-loop makes the function print every time it is encountered (and thus filling the console). Instead, I have modified the function to return the pie
object, so you can store it in a variable.
Hope this helps.
Edit:
Your new concise function illustrates the problem. Compare:
buffon01(1e6, a=3, l=2)
#$`pi`
#[1] 3.143023
#
#$error
#[1] 0.00143062
buffon01(1e6, a=2, l=3)
#`pi`
#[1] 3.850819
#$error
#[1] 0.7092266
Here, you see that using l>a fails because the wrong formula is used. In regards to convergence to pi, Buffon's needle is quite slow to converge and a lot of throws are needed to get a decent estimate. But that is statistical question, which is touched upon here.