The familiar code for estimating pi is as follows:
import math,random
random.seed(777)
j = pie = 1
while True:
pie = pie + math.trunc(random.random()**2 + random.random()**2)
if j%100000==0: print(4*(1-float(pie)/float(j)))
j = j + 1
print('done')
which emulates darts being thrown at a two-dimensional dartboard. But when you try to elevate to a three-dimensional dartboard with:
import math,random
random.seed(777)
j = pie = 1
while True:
pie = pie + math.trunc(random.random()**2 + random.random()**2 + random.random()**2)
if j%100000==0: print((3.0/4.0)*8.0*(1-float(pie)/float(j)))
j = j + 1
print('done')
you get something other than pi.
Generally, I agree with the solution proposed by @Bob__ as it's more straightforward. Having said that, your solution can be generalized to 3 dimensional dartboard:
import math,random
random.seed(777)
j = pie = 1
pie = 0
while True:
# pie = pie + math.trunc(random.random()**2 + random.random()**2 + random.random()**2)
pie = pie + min(1, math.trunc(random.random()**2 + random.random()**2 + random.random()**2))
if j%100000==0: print((3.0/4.0)*8.0*(1-float(pie)/float(j)))
j = j + 1
print('done')
To understand the issue we need to clarify what the pie
variable really does. It contains the number of cases where a random radius is longer than 1.0 (so beyond the 3D dartboard).
The 2D case works because math.trunc
always returns either 0 or 1 (in or out) but for 3D it returns either 0 or 1 or 2. So, in case of 3D, it fails because it sometimes increases pie
by 2 and, thus, converges faster.
To fix your example, you just need to make sure that pie
is never increased by more than 1 at a time.