Skip to content

Instantly share code, notes, and snippets.

@elbeno
Created March 5, 2017 22:46
Show Gist options
  • Save elbeno/aace93b23510450ef95c0cb45120cf37 to your computer and use it in GitHub Desktop.
Save elbeno/aace93b23510450ef95c0cb45120cf37 to your computer and use it in GitHub Desktop.
Expressive code to (poorly) approximate pi
// 2017 Pi Day challenge:
// http://www.fluentcpp.com/2017/03/02/the-pi-day-challenge-for-expressive-code-in-c/
#include <algorithm>
#include <array>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <random>
#include <utility>
using namespace std;
// a coordinate is a pair of doubles
using coord_t = pair<double, double>;
// run a function n times, and count the number of values produced that satisfy
// a predicate
template <typename F, typename Size, typename Pred>
auto count_if_generate_n(F&& f, Size n, Pred&& p)
{
Size count{};
while (n-- > 0) {
if (p(f())) ++count;
}
return count;
}
// initialize the RNG
decltype(auto) init_RNG()
{
array<int, mt19937::state_size> seed_data;
random_device rd;
generate_n(seed_data.data(), seed_data.size(), ref(rd));
seed_seq seq(begin(seed_data), end(seed_data));
static mt19937 gen(seq);
return (gen);
}
// the value of pi we're using as a yardstick
const double pi = 3.14159265359;
int main()
{
// initialize RNG, pad output with spaces
auto& gen = init_RNG();
cout.fill(' ');
for (auto r_power = 0; r_power < 9; ++r_power)
{
for (auto n_power = 0; n_power < 7; ++n_power)
{
// radius & number of iterations
const auto r = pow(10.0, r_power);
const auto n = static_cast<int>(pow(10, n_power));
// coordinates are generated in the square of size 2r
auto d = uniform_real_distribution<double>(-r, r);
// count how many random samples fall within a circle
const auto hits = count_if_generate_n(
[&] () -> coord_t { return {d(gen), d(gen)}; },
n,
[&] (const auto& c) { return hypot(c.first, c.second) <= r; });
// not-a-very-good approximation to pi
double pi_approx = hits * 4 / static_cast<double>(n);
cout << setw(12) << abs(pi_approx - pi) << ' ';
}
cout << '\n';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment