Skip to content

Instantly share code, notes, and snippets.

@arnemertz
Last active March 15, 2017 00:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnemertz/5c2a049c2260c9539f43534aec1fcbaa to your computer and use it in GitHub Desktop.
Save arnemertz/5c2a049c2260c9539f43534aec1fcbaa to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <random>
#include <cassert>
struct coordinates {
double x;
double y;
};
struct bounding_box {
coordinates min;
coordinates max;
};
class random_point_generator {
static inline std::mt19937 gen{std::random_device{}()};
std::uniform_real_distribution<double> dist_x;
std::uniform_real_distribution<double> dist_y;
public:
explicit random_point_generator(bounding_box box)
: dist_x{box.min.x, box.max.x}
, dist_y{box.min.y, box.max.y}
{}
coordinates operator()() {
return {dist_x(gen), dist_y(gen)};
}
};
auto generate_random_points(std::size_t points_total, bounding_box box) {
std::vector<coordinates> points(points_total, {0,0});
std::generate(begin(points), end(points), random_point_generator{box});
return points;
}
bounding_box centered_quadratic_bounding_box(double max_coordinate) {
assert(max_coordinate > 0.0);
return {{-max_coordinate, -max_coordinate}, {max_coordinate, max_coordinate}};
}
auto is_in_centered_circle(double radius) {
auto predicate = [=](coordinates point){
return hypot(point.x, point.y) < radius;
};
return predicate;
}
double approximate_pi(std::size_t points_count_total, double radius){
auto random_points = generate_random_points(points_count_total, centered_quadratic_bounding_box(radius));
auto points_count_in_circle = std::count_if(begin(random_points), end(random_points), is_in_centered_circle(radius));
auto approximated_pi = 4.0 * static_cast<double>(points_count_in_circle) / static_cast<double>(points_count_total);
return approximated_pi;
}
double difference_to_pi(double pi_candidate) {
const static double pi = 3.14159265359;
return std::abs(pi - pi_candidate);
}
int main() {
for (auto radius_exp : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) {
for (auto point_count_exp : {0, 1, 2, 3, 4, 5, 6, 7}) {
double radius = std::pow(10, radius_exp);
auto point_count = static_cast<std::size_t>(std::pow(10, point_count_exp));
auto approximated_pi = approximate_pi(point_count, radius);
auto difference = difference_to_pi(approximated_pi);
std::cout << difference << '\t';
}
std::cout << '\n';
}
}
@scraimer
Copy link

That trick with the initializer list in the for loop is brilliant! (I'm talking about for (auto radius_exp : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
I can just imagine some of the old-school C++ engineers cringing when I show this to them. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment