<?php
class SeededRandomNumberGenerator
{
// An integer with the 32 least significant bits set
// 0xffffffff is a float on 32-bit platforms :-/
const MASK = \PHP_INT_SIZE === 4 ? ~0 : 0xffffffff;
private $seed;
public function __construct(int $seed)
{
$this->seed = $seed & self::MASK;
}
/**
* Add two integers, wrap around on overflow (avoid float coersion)
* https://stackoverflow.com/questions/4068033/add-two-integers-using-only-bitwise-operators
*/
private static function intAdd(int $a, int $b): int
{
$a &= self::MASK;
$b &= self::MASK;
$carry = $a & $b;
$result = $a ^ $b;
while ($carry) {
$carry &= self::MASK;
$shiftedCarry = $carry << 1;
$carry = $result & $shiftedCarry;
$result ^= $shiftedCarry;
}
return $result & self::MASK;
}
/**
* Multiply two integers, wrap around on overflow (avoid float coersion)
* https://stackoverflow.com/questions/4456442/multiplication-of-two-integers-using-bitwise-operators
*/
private static function intMul(int $a, int $b): int
{
$a &= self::MASK;
$b &= self::MASK;
$result = 0;
while ($b) {
if ($b & 0b1) {
$result = self::intAdd($result, $a);
}
$a = ($a << 1) & self::MASK;
$b >>= 1;
}
return $result;
}
/**
* Generate a pseudo-random number from a seed
* https://stackoverflow.com/questions/4768180/rand-implementation
*/
public function generate()
{
return (($this->seed = self::intAdd(self::intMul($this->seed, 214013), 2531011)) >> 16) & 0x7fff;
}
}
$gen = new SeededRandomNumberGenerator(7623);
for ($i = 0; $i < 15; $i++) {
echo "{$gen->generate()}\n";
}
- Output for 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.19, 8.3.0 - 8.3.7
- 24932
22821
16009
1813
26424
28075
10547
32677
16415
22132
25244
3420
10592
8892
10207
- Output for 5.6.0 - 5.6.40
- Parse error: syntax error, unexpected ':', expecting ';' or '{' in /in/3YOCE on line 20
Process exited with code 255.
preferences:
260.3 ms | 401 KiB | 293 Q