I recently came across an interesting math problem on youtube (why youtube keeps showing me these when I’m watching cooking shows, I’ll never understand, but I digress). What is the average distance between two random points on a circle? This can also be expanded to ask what is the average distance between two random points inside a circle? Now of course I’m not going to sit down and do lots of math to figure this out, but it is a kinda interesting problem for a monte carlo simulation. So I dusted the python off and went to work.
A quick note before we begin: I did all of my simulations assuming a radius of 1. You can alter it very slightly and change the radius to anything you want, but that’s an exercise left to the reader. Or you can just multiply the answer you get with a radius of 1 by the radius you want, and get the same answer. 🙂
Answering the first problem is actually really easy. You just iterate through however many tests you want to do and for each one, you generate two random points on the edge of a circle and then calculate the distance and average it when you’re done. To generate two random points I just generated a random angle then found the x, y point using the angle and radius of 1. (Quick tip, in most programming languages cos and sin are using radians so you’ll need to convert.)
# Created by mwwalk 10/20/2018 # This program finds the average distance between any two random points # on a circle of radius 1. It does this by calculating two random angles # then the points on the edge of the circle associated with those angles, # then finds the distance between those two points. import random #imports the RNG from math import sin,cos,pi,sqrt #for cos, sin, and pi totalDistance = 0 numTests = 10000000 # Iterates through "numTests" number of distances for i in range(numTests): # Find point number 1 by generating a random angle, # then finding the point on the circle at that angle angle = random.random()*360 angle = angle*pi/180 x1 = cos(angle) y1 = sin(angle) # Find point number 2 a slightly different way (with radians) angle = random.random()*2*pi x2 = cos(angle) y2 = sin(angle) # Find distance between the two points # Using two different methods of squaring totalDistance += sqrt((x2-x1)**2 + pow(y2-y1, 2)) # Print average and print "Our average: " + str(totalDistance/numTests) print "Math answer: " + str(4/pi)
For this first problem, we get an answer (depending on how many iterations you do) of about 1.273 and converging on the correct answer of 4r/pi.
The second problem appears to be only slightly harder. Instead of assuming a radius of one, we need to generate a random radius between 0 and 1 and use that. But there’s a catch! If you think you can just use the random function to grab a random number from 0 to 1, you’ll end up with most of your points clustered around the center of the circle and fewer around the outer edge. There are two ways you can get an even distribution. The first is the most straightforward. Just generate a random x from -1 to 1 and a random y from -1 to 1. Then, calculate the distance from the x,y point to 0,0 and if it’s more than one then it’s outside the circle so discard it and start over. Another method is quicker (discussed here). Instead of a uniform distribution, the random radius should be calculated a: r = R * sqrt(random()) where R is one in our case.
# Created by mwwalk 10/20/2018 # This program finds the average distance between any two random points # inside a circle of radius 1. It does this in two different ways. The first # way is to generate a random x,y pair and then check to see if it's in the # circle and if not, try again. The second way generates a random angle and # random radius and gets the x,y pair from that, but you have to be careful # when making the random radius becau<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>se a uniform distribution would concentrate # the points around the center of the circle. import random #imports the RNG from math import sin,cos,pi,sqrt #for cos, sin, and pi totalDistance = 0 average = 0 numTests = 100000 x1 = y1 = x2 = y2 = 0 # Iterates through "numTests" number of distances for i in range(numTests): # One method of getting random points within a circle # Just generate two random points and then check to see if they're # in the circle. If not, just discard them and make new points. while (True): x1 = random.random() * 2 - 1 y1 = random.random() * 2 - 1 if (1 > sqrt(x1*x1 + y1*y1)): break while (True): x2 = random.random() * 2 - 1 y2 = random.random() * 2 - 1 if (1 > sqrt(x2*x2 + y2*y2)): break # Another way to find a random point in a circle would be to find # a random radius and random angle then find the x,y point for that. # But if you do that, you will end up with a heavier distribution of points # around the center of the circle so you have to alter how you choose the radius. r1 = sqrt(random.random()) a1 = random.random()*360 x1 = r1 * cos(a1*180/pi) y1 = r1 * sin(a1*180/pi) r2 = sqrt(random.random()) a2 = random.random()*360 x2 = r2 * cos(a2*180/pi) y2 = r2 * sin(a2*180/pi) # Find distance between the two points # Using two different methods of squaring totalDistance += sqrt((x2-x1)**2 + pow(y2-y1, 2)) # Print average and print "Our average: " + str(totalDistance/numTests) print "Math answer: " + str(128.0/45/pi)
And for this problem, we get the answer of about 0.905 and converging on the correct answer of 128/(45*pi).
Any questions? Leave them in the comments below!