Skip to content

Commit b031a0b

Browse files
Adding PiApproximation algo (#6602)
* Adding PiApproximation algo * Added clang formatting * Added private method * checkstyle fix * checkstyle fix --------- Co-authored-by: Deniz Altunkapan <[email protected]>
1 parent 5f8d8ee commit b031a0b

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.thealgorithms.maths;
2+
import java.util.ArrayList;
3+
import java.util.List;
4+
import java.util.Random;
5+
6+
/**
7+
* Implementation to calculate an estimate of the number π (Pi).
8+
*
9+
* We take a random point P with coordinates (x, y) such that 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1.
10+
* If x² + y² ≤ 1, then the point is inside the quarter disk of radius 1,
11+
* else the point is outside. We know that the probability of the point being
12+
* inside the quarter disk is equal to π/4.
13+
*
14+
*
15+
* @author [Yash Rajput](https://github.com/the-yash-rajput)
16+
*/
17+
public final class PiApproximation {
18+
19+
private PiApproximation() {
20+
throw new AssertionError("No instances.");
21+
}
22+
23+
/**
24+
* Structure representing a point with coordinates (x, y)
25+
* where 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1.
26+
*/
27+
static class Point {
28+
double x;
29+
double y;
30+
31+
Point(double x, double y) {
32+
this.x = x;
33+
this.y = y;
34+
}
35+
}
36+
37+
/**
38+
* This function uses the points in a given list (drawn at random)
39+
* to return an approximation of the number π.
40+
*
41+
* @param pts List of points where each point contains x and y coordinates
42+
* @return An estimate of the number π
43+
*/
44+
public static double approximatePi(List<Point> pts) {
45+
double count = 0; // Points in circle
46+
47+
for (Point p : pts) {
48+
if ((p.x * p.x) + (p.y * p.y) <= 1) {
49+
count++;
50+
}
51+
}
52+
53+
return 4.0 * count / pts.size();
54+
}
55+
56+
/**
57+
* Generates random points for testing the Pi approximation.
58+
*
59+
* @param numPoints Number of random points to generate
60+
* @return List of random points
61+
*/
62+
public static List<Point> generateRandomPoints(int numPoints) {
63+
List<Point> points = new ArrayList<>();
64+
Random rand = new Random();
65+
66+
for (int i = 0; i < numPoints; i++) {
67+
double x = rand.nextDouble(); // Random value between 0 and 1
68+
double y = rand.nextDouble(); // Random value between 0 and 1
69+
points.add(new Point(x, y));
70+
}
71+
72+
return points;
73+
}
74+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import org.junit.jupiter.api.Test;
9+
10+
class PiApproximationTest {
11+
12+
private static final double DELTA = 0.5; // Tolerance for Pi approximation
13+
private static final double TIGHT_DELTA = 0.1; // Tighter tolerance for large samples
14+
15+
/**
16+
* Test with known points that are all inside the quarter circle.
17+
*/
18+
@Test
19+
public void testAllPointsInside() {
20+
List<PiApproximation.Point> points = new ArrayList<>();
21+
points.add(new PiApproximation.Point(0.0, 0.0)); // Origin
22+
points.add(new PiApproximation.Point(0.5, 0.5)); // Inside
23+
points.add(new PiApproximation.Point(0.3, 0.3)); // Inside
24+
25+
double result = PiApproximation.approximatePi(points);
26+
// All points inside, so result should be 4.0
27+
assertEquals(4.0, result, 0.001);
28+
}
29+
30+
/**
31+
* Test with known points that are all outside the quarter circle.
32+
*/
33+
@Test
34+
public void testAllPointsOutside() {
35+
List<PiApproximation.Point> points = new ArrayList<>();
36+
points.add(new PiApproximation.Point(1.0, 1.0)); // Corner - outside
37+
points.add(new PiApproximation.Point(0.9, 0.9)); // Outside
38+
39+
double result = PiApproximation.approximatePi(points);
40+
// No points inside, so result should be 0.0
41+
assertEquals(0.0, result, 0.001);
42+
}
43+
44+
/**
45+
* Test with mixed points (some inside, some outside).
46+
*/
47+
@Test
48+
public void testMixedPoints() {
49+
List<PiApproximation.Point> points = new ArrayList<>();
50+
// Inside points
51+
points.add(new PiApproximation.Point(0.0, 0.0));
52+
points.add(new PiApproximation.Point(0.5, 0.5));
53+
// Outside points
54+
points.add(new PiApproximation.Point(1.0, 1.0));
55+
points.add(new PiApproximation.Point(0.9, 0.9));
56+
57+
double result = PiApproximation.approximatePi(points);
58+
// 2 out of 4 points inside: 4 * 2/4 = 2.0
59+
assertEquals(2.0, result, 0.001);
60+
}
61+
62+
/**
63+
* Test with boundary point (on the circle).
64+
*/
65+
@Test
66+
public void testBoundaryPoint() {
67+
List<PiApproximation.Point> points = new ArrayList<>();
68+
points.add(new PiApproximation.Point(1.0, 0.0)); // On circle: x² + y² = 1
69+
points.add(new PiApproximation.Point(0.0, 1.0)); // On circle
70+
71+
double result = PiApproximation.approximatePi(points);
72+
// Boundary points should be counted as inside (≤ 1)
73+
assertEquals(4.0, result, 0.001);
74+
}
75+
76+
/**
77+
* Test with small random sample (moderate accuracy expected).
78+
*/
79+
@Test
80+
public void testSmallRandomSample() {
81+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(1000);
82+
double result = PiApproximation.approximatePi(points);
83+
84+
// With 1000 points, result should be reasonably close to π
85+
assertEquals(Math.PI, result, DELTA);
86+
}
87+
88+
/**
89+
* Test with large random sample (better accuracy expected).
90+
*/
91+
@Test
92+
public void testLargeRandomSample() {
93+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(100000);
94+
double result = PiApproximation.approximatePi(points);
95+
96+
// With 100000 points, result should be very close to π
97+
assertEquals(Math.PI, result, TIGHT_DELTA);
98+
}
99+
100+
/**
101+
* Test that result is always positive.
102+
*/
103+
@Test
104+
public void testResultIsPositive() {
105+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(1000);
106+
double result = PiApproximation.approximatePi(points);
107+
108+
assertTrue(result >= 0, "Pi approximation should be positive");
109+
}
110+
111+
/**
112+
* Test that result is bounded (0 ≤ result ≤ 4).
113+
*/
114+
@Test
115+
public void testResultIsBounded() {
116+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(1000);
117+
double result = PiApproximation.approximatePi(points);
118+
119+
assertTrue(result >= 0 && result <= 4, "Pi approximation should be between 0 and 4");
120+
}
121+
122+
/**
123+
* Test with single point inside.
124+
*/
125+
@Test
126+
public void testSinglePointInside() {
127+
List<PiApproximation.Point> points = new ArrayList<>();
128+
points.add(new PiApproximation.Point(0.0, 0.0));
129+
130+
double result = PiApproximation.approximatePi(points);
131+
assertEquals(4.0, result, 0.001);
132+
}
133+
134+
/**
135+
* Test with single point outside.
136+
*/
137+
@Test
138+
public void testSinglePointOutside() {
139+
List<PiApproximation.Point> points = new ArrayList<>();
140+
points.add(new PiApproximation.Point(1.0, 1.0));
141+
142+
double result = PiApproximation.approximatePi(points);
143+
assertEquals(0.0, result, 0.001);
144+
}
145+
146+
/**
147+
* Test that generated points are within valid range [0, 1].
148+
*/
149+
@Test
150+
public void testGeneratedPointsInRange() {
151+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(100);
152+
153+
for (PiApproximation.Point p : points) {
154+
assertTrue(p.x >= 0 && p.x <= 1, "X coordinate should be between 0 and 1");
155+
assertTrue(p.y >= 0 && p.y <= 1, "Y coordinate should be between 0 and 1");
156+
}
157+
}
158+
159+
/**
160+
* Test that the correct number of points are generated.
161+
*/
162+
@Test
163+
public void testCorrectNumberOfPointsGenerated() {
164+
int expectedSize = 500;
165+
List<PiApproximation.Point> points = PiApproximation.generateRandomPoints(expectedSize);
166+
167+
assertEquals(expectedSize, points.size());
168+
}
169+
}

0 commit comments

Comments
 (0)