1
0
mirror of https://github.com/php/php-src.git synced 2026-04-29 03:03:26 +02:00
Files
Tim Düsterhus 582b724c35 random: Fix γ-section implementation for Randomizer::getFloat() (#12402)
The reference implementation of the "Drawing Random Floating-Point Numbers from
an Interval" paper contains two mistakes that will result in erroneous values
being returned under certain circumstances:

- For large values of `g` the multiplication of `k * g` might overflow to
  infinity.
- The value of `ceilint()` might exceed 2^53, possibly leading to a rounding
  error when promoting `k` to double within the multiplication of `k * g`.

This commit updates the implementation based on Prof. Goualard suggestions
after reaching out to him. It will correctly handle inputs larger than 2^-1020
in absolute values. This limitation will be documented and those inputs
possibly be rejected in a follow-up commit depending on performance concerns.
2023-10-13 17:55:14 +02:00

42 lines
803 B
PHP

--TEST--
Random: Randomizer: getFloat(): Extreme ranges are handled correctly
--FILE--
<?php
use Random\Engine;
use Random\Randomizer;
final class TestEngine implements Engine
{
private array $values = [
"\x64\xe8\x58\x79\x3e\xf6\x38\x00",
"\x65\xe8\x58\x79\x3e\xf6\x38\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
];
public function generate(): string
{
return \array_shift($this->values);
}
}
$r = new Randomizer(new TestEngine());
$min = -1.6e308;
$max = 1.6e308;
printf("%.17g\n", $min);
printf("%.17g\n\n", $max);
printf("%.17g\n", $r->getFloat($min, $max));
printf("%.17g\n", $r->getFloat($min, $max));
printf("%.17g\n", $r->getFloat($min, $max));
?>
--EXPECT--
-1.6e+308
1.6e+308
-1.5999999999999998e+308
-1.6e+308
1.5999999999999998e+308