EN
JavaScript - how to use Monte Carlo method to calculate pi constant number?
6 points
Using JavaScript it is possible to calculate surface area (definite integral) in the following way.
Main idea of this method is to:
- random big amount of points
- check all time if every next one point is inside a circle or not,
- compute coefficient by dividing number of points inside of circle by outside one point
- multiply the coefficient by square surface area - this way from proportion it is possible to get approximated circle surface area,
- use transformed circle surface area formula to calculate
PI
number.
Note: the longer the simulation is performed, the results are more precised.
xxxxxxxxxx
1
2
<html>
3
<head>
4
<style>
5
6
#my-canvas { border: 1px solid gray; }
7
8
</style>
9
<script>
10
11
function randomizePoint(range) {
12
return range * (Math.random() - 0.5);
13
}
14
15
// This method checks the point is inside circle
16
// with center at (0, 0) point.
17
//
18
function checkCondition(circleRadius, pointX, pointY) {
19
var pointRadius = Math.sqrt(pointX * pointX + pointY * pointY);
20
21
if (pointRadius <= circleRadius) {
22
return true;
23
}
24
25
return false;
26
}
27
28
window.Drawer = function(canvas) {
29
var context = canvas.getContext('2d');
30
31
var xCenter = canvas.width / 2;
32
var yCenter = canvas.height / 2;
33
34
this.clearCanvas = function() {
35
context.clearRect(0, 0, canvas.width, canvas.height);
36
};
37
38
this.drawPoint = function(x, y, color) {
39
40
var tmpX = Math.round(xCenter + x - 1);
41
var tmpY = Math.round(yCenter + y - 1);
42
43
context.strokeStyle = '#fff';
44
context.fillStyle = color || '#000';
45
46
context.fillRect(tmpX, tmpY, 2, 2);
47
};
48
49
this.drawCircle = function(x, y, radius) {
50
51
var tmpX = Math.round(xCenter + x - 1);
52
var tmpY = Math.round(yCenter + y - 1);
53
54
context.lineWidth = 0.5;
55
context.strokeStyle = '#ff0000';
56
context.fillStyle = '#fff';
57
58
context.beginPath();
59
context.arc(tmpX, tmpY, radius, 0, 2 * Math.PI);
60
context.stroke();
61
};
62
};
63
64
</script>
65
</head>
66
<body>
67
<canvas id="my-canvas" width="300" height="300"></canvas>
68
<script>
69
70
var canvas = document.querySelector('#my-canvas');
71
72
var drawer = new Drawer(canvas);
73
74
var squareArea = canvas.width * canvas.height;
75
var circleRadius = 150;
76
77
var squarePointsCount = 0;
78
var circlePointsCount = 0;
79
80
drawer.clearCanvas();
81
drawer.drawCircle(0, 0, circleRadius);
82
83
function makeIteration() {
84
85
for(var i = 0; i < 100; ++i) {
86
87
// random coordinates from range -150 to +150
88
var pointX = randomizePoint(canvas.width);
89
var pointY = randomizePoint(canvas.height);
90
91
if (checkCondition(circleRadius, pointX, pointY)) {
92
drawer.drawPoint(pointX, pointY, 'red');
93
94
circlePointsCount += 1;
95
} else {
96
drawer.drawPoint(pointX, pointY, 'silver');
97
}
98
99
squarePointsCount += 1;
100
}
101
102
// next iterations gives computation better precision
103
// according to number of randomized points
104
105
var randomPointsProportion = circlePointsCount / squarePointsCount;
106
107
var computatedCircleArea = randomPointsProportion * squareArea;
108
var computatedPI = computatedCircleArea / (circleRadius * circleRadius);
109
110
var computationError = Math.abs(Math.PI - computatedPI);
111
112
console.clear();
113
114
console.log('PI number:');
115
console.log(' Expected: ' + Math.PI);
116
console.log(' Computed: ' + computatedPI);
117
console.log(' Error: ' + computationError);
118
}
119
120
setInterval(makeIteration, 100);
121
122
</script>
123
</body>
124
</html>