We reuse the setup from the computation of $\pi$, but run this many times for a number of sample counts.
import numpy as np
import matplotlib.pyplot as plt
sample_counts = np.arange(10, 2000, 20)
nexperiments = 1000
avg_errors = []
for nsamples in sample_counts:
errors = []
for experiment in range(nexperiments):
# draw samples
samples = np.random.rand(2, nsamples)
# compute p
p = np.zeros(nsamples)
r = samples[0]**2 + samples[1]**2
p[r<=1] = 1
approx_pi = 4*np.sum(p) / nsamples
errors.append(np.abs(approx_pi - np.pi))
avg_errors.append(np.sum(errors)/nexperiments)
avg_errors = np.array(avg_errors)
plt.loglog(sample_counts, avg_errors)
plt.xlabel("# Samples")
plt.ylabel("Error")
plt.grid()
Empirically: Average error
$$E=O(\frac1{\sqrt n})$$Precise statement: Central Limit Theorem