|
1 | 1 | /**
|
2 | 2 | * @file
|
3 |
| - * @brief Implementation to calculate an estimate of the [number π (Pi)](https://en.wikipedia.org/wiki/File:Pi_30K.gif). |
| 3 | + * @brief |
| 4 | + * Implementation to calculate an estimate of the [number π |
| 5 | + * (Pi)](https://en.wikipedia.org/wiki/File:Pi_30K.gif). |
4 | 6 | *
|
5 | 7 | * @details
|
6 |
| - * We take a random point P with coordinates (x, y) such that 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1. If x² + y² ≤ 1, then the |
7 |
| - * point is inside the quarter disk of radius 1, otherwise the point is outside. |
8 |
| - * We know that the probability of the point being inside the quarter disk is equal to π/4 |
9 |
| - * double approx(vector<Point> &pts) which will use the points pts (drawn at random) to |
10 |
| - * return an estimate of the number π |
11 |
| - * \note This implementation is better than naive recursive or iterative |
| 8 | + * We take a random point P with coordinates (x, y) such that 0 ≤ x ≤ 1 and 0 ≤ |
| 9 | + * y ≤ 1. If x² + y² ≤ 1, then the point is inside the quarter disk of radius 1, |
| 10 | + * else the point is outside. We know that the probability of the point being |
| 11 | + * inside the quarter disk is equal to π/4 double approx(vector<Point> &pts) |
| 12 | + * which will use the points pts (drawn at random) to return an estimate of the |
| 13 | + * number π |
| 14 | + * @note This implementation is better than naive recursive or iterative |
12 | 15 | * approach.
|
13 | 16 | *
|
14 | 17 | * @author [Qannaf AL-SAHMI](https://github.com/Qannaf)
|
15 | 18 | */
|
16 | 19 |
|
| 20 | +#include <cassert> /// for assert |
| 21 | +#include <cstdlib> /// for std::rand |
17 | 22 | #include <iostream> /// for IO operations
|
18 | 23 | #include <vector> /// for std::vector
|
19 |
| -#include <cstdlib> /// for std::rand |
20 | 24 |
|
21 | 25 | /**
|
22 | 26 | * @namespace math
|
23 | 27 | * @brief Mathematical algorithms
|
24 | 28 | */
|
25 | 29 | namespace math {
|
26 | 30 |
|
27 |
| - /** |
28 |
| - * structure of points containing two numbers, respectively x and y such that 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1. |
29 |
| - */ |
30 |
| - typedef struct { |
| 31 | +/** |
| 32 | + * @brief structure of points containing two numbers, x and y, such that 0 ≤ x ≤ |
| 33 | + * 1 and 0 ≤ y ≤ 1. |
| 34 | + */ |
| 35 | +using Point = struct { |
31 | 36 | double x;
|
32 | 37 | double y;
|
33 |
| - } Point; |
| 38 | +}; |
34 | 39 |
|
35 |
| - double approximate_pi(const std::vector<Point> &pts) { |
36 |
| - /** |
37 |
| - * This function use the points pts (drawn at random) to return an estimate of the number π using the given points |
38 |
| - * @param pts Each item of pts contains a point. A point is represented by a structure containing exactly |
39 |
| - * two numbers, respectively x and y such that 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1. |
40 |
| - * pts always contains at least one item |
41 |
| - * @return an estimate of the number π |
42 |
| - */ |
43 |
| - { |
44 |
| - int count =0; // Points in cercle |
45 |
| - for(Point p:pts) |
46 |
| - if(p.x * p.x + p.y*p.y <= 1) |
47 |
| - ++count; |
48 |
| - |
49 |
| - return 4.0*count/pts.size(); |
| 40 | +/** |
| 41 | + * @brief This function uses the points in a given vector 'pts' (drawn at |
| 42 | + * random) to return an approximation of the number π. |
| 43 | + * @param pts Each item of pts contains a point. A point is represented by the |
| 44 | + * point structure (coded above). |
| 45 | + * @return an estimate of the number π. |
| 46 | + */ |
| 47 | +double approximate_pi(const std::vector<Point> &pts) { |
| 48 | + double count = 0; // Points in circle |
| 49 | + for (Point p : pts) { |
| 50 | + if ((p.x * p.x) + (p.y * p.y) <= 1) { |
| 51 | + count++; |
50 | 52 | }
|
51 | 53 | }
|
| 54 | + return 4.0 * count / static_cast<double>(pts.size()); |
| 55 | +} |
52 | 56 | } // namespace math
|
53 | 57 |
|
54 | 58 | /**
|
55 | 59 | * @brief Self-test implementations
|
56 | 60 | * @returns void
|
57 | 61 | */
|
58 |
| -static void test() { |
59 |
| - std::vector<math::Point> rands; |
| 62 | +static void tests() { |
| 63 | + std::vector<math::Point> rands; |
60 | 64 | for (std::size_t i = 0; i < 100000; i++) {
|
61 | 65 | math::Point p;
|
62 |
| - p.x = rand() / (double)RAND_MAX; // 0 <= x <= 1 |
63 |
| - p.y = rand() / (double)RAND_MAX; // 0 <= y <= 1 |
| 66 | + p.x = rand() / static_cast<double>(RAND_MAX); // 0 <= x <= 1 |
| 67 | + p.y = rand() / static_cast<double>(RAND_MAX); // 0 <= y <= 1 |
64 | 68 | rands.push_back(p);
|
65 | 69 | }
|
66 |
| - std::cout << math::approximate_pi(rands) << std::endl; // ~3.14 |
| 70 | + assert(math::approximate_pi(rands) > 3.135); |
| 71 | + assert(math::approximate_pi(rands) < 3.145); |
| 72 | + |
| 73 | + std::cout << "All tests have successfully passed!" << std::endl; |
67 | 74 | }
|
68 | 75 |
|
69 | 76 | /**
|
70 | 77 | * @brief Main function
|
71 |
| - * @param argc commandline argument count (ignored) |
72 |
| - * @param argv commandline array of arguments (ignored) |
73 | 78 | * @returns 0 on exit
|
74 | 79 | */
|
75 |
| -int main(int argc, char *argv[]) { |
76 |
| - test(); // run self-test implementations |
| 80 | +int main() { |
| 81 | + tests(); // run self-test implementations |
77 | 82 | return 0;
|
78 | 83 | }
|
0 commit comments