Skip to content

Instantly share code, notes, and snippets.

@drupol
Last active January 9, 2020 11:19
Show Gist options
  • Save drupol/b5c0f489b7dd901ece710bb3542db405 to your computer and use it in GitHub Desktop.
Save drupol/b5c0f489b7dd901ece710bb3542db405 to your computer and use it in GitHub Desktop.
Approximate PI using Monte Carlo method
<?php
declare(strict_types=1);
include 'vendor/autoload.php';
use loophp\collection\Collection;
$monteCarloMethod = static function ($in = 0, $total = 1) {
$randomNumber1 = mt_rand() / mt_getrandmax();
$randomNumber2 = mt_rand() / mt_getrandmax();
if (1 >= (($randomNumber1 ** 2) + ($randomNumber2 ** 2))) {
++$in;
}
return [$in, ++$total];
};
$precision = new class() {
/**
* @var array
*/
private $state;
/**
* @var float
*/
private $precision;
/**
* @var int
*/
private $row;
/**
* Precision constructor.
*
* @param float $precision
* @param int $row
*/
public function __construct(float $precision = 10 ** -4, int $row = 100)
{
$this->precision = $precision;
$this->row = $row;
$this->state = [
'prev' => null,
'found' => 0,
];
}
/**
* @param float $value
*
* @return bool
*/
public function __invoke(float $value): bool
{
if (null === $this->state['prev']) {
$this->state['prev'] = $value;
$this->state['found'] = 0;
return false;
}
if ($value === $this->state['prev']) {
$this->state['found'] = 0;
return false;
}
if (abs($value - $this->state['prev']) <= $this->precision) {
++$this->state['found'];
return false;
}
if ($this->state['found'] >= $this->row) {
$this->state['found'] = 0;
return true;
}
$this->state['prev'] = $value;
$this->state['found'] = 0;
return false;
}
};
$pi_approximation = Collection::iterate($monteCarloMethod)
->map(
static function ($value) {
return 4 * $value[0] / $value[1];
}
)
->nth(50) // Take every 50
->until($precision)
->last();
print_r($pi_approximation);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment