Re: [PHP-DEV] ext-random: add random_float() ?
2022年12月29日(木) 22:25 Tim Düsterhus : > Hi > > On 12/20/22 07:27, Go Kudo wrote: > > Now that my work is done, I was thinking about a proposal for a > sunsetting > > of existing functions for PHP 8.3 based on the features introduced in > > ext-random, and I realized that there is no alternative to `lcg_value()`. > > > > Essentially, this could be completely replaced by > > Random\Randomizer::getFloat(), but there are easier `random_int()` and > > `random_bytes()` functions for ints and strings. > > > > The Randomizer may be overkill and complicated for PHP use cases where > > random number reproducibility is not required in many cases. > > > > So, why not add a `random_float(): float` function? This function, like > the > > others, uses CSPRNG and returns a value between 0.0 and 1.0. This > behavior > > is `Closed` `Closed`. > > > > Opinions are welcome. > > I'm not convinced that a random_float() function is a good addition. > Especially not with the proposed behavior: > > 1. Using the (0, 1, ClosedClosed) behavior does neither match > Randomizer::nextFloat(), nor Randomizer::getFloat(). > > 2. I consider the ClosedOpen behavior to be the "correct" default, > because the interval can then be cleanly split into equally sized > subintervals. > > > > But even when random_float() would work like Randomizer::nextFloat() > (i.e. (0, 1, ClosedOpen)), I would not consider this a good addition: > > Users would likely attempt to scale the returned value to arbitrary > ranges using the `($min + random_float() * ($max - $min))` construction, > instead of using Randomizer::getFloat(). > > As per Drawing Random Floating-Point Numbers from an Interval. Frédéric > Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022 this construction > is unsafe, because is is both biased and also may return values outside > the expected interval. > > > > So random_float() would rather need to behave like > Randomizer::getFloat() instead of Randomizer::nextFloat() and then it > would not be much simpler than using the Randomizer class directly. I > further expect that needing to generate random floats is much rarer than > needing to generate random integers or random bytes (for tokens), thus > having convenience functions for those two, but not floats is acceptable > and keeps the API surface simple, making it easier to document all the > gotchas. Users can add convenience wrappers themselves. > > Best regards > Tim Düsterhus > Hi Tim Thank you for the clear explanation. I generally understood the intent. And once again I recognized that floating point random numbers are difficult to handle. I agree that the addition of the random_float() function is inappropriate. However, with the goal of deprecating it in PHP 8.3 and deprecating RNGs with virtual machine dependent state in PHP 9.x, I think we need to provide a useful replacement for the lcg_value() function. Do you have any good ideas on this? Most likely, since the random numbers generated by lcg_value() are of low quality and do not appear to be used very often, one idea would be to simply remove it. However, I believe that the absence of an alternative function is likely to generate negative opinions about its elimination. Regards, Go Kudo
Re: [PHP-DEV] ext-random: add random_float() ?
Hi On 12/20/22 09:15, Hans Henrik Bergan wrote: btw while we're on the topic, does anyone know if this function gives biased results/is-safe or not? i honestly don't know: function random_float(float $min, float $max): float { if ($min > $max) throw new \InvalidArgumentException("min must be less than max"); if ($min === $max) return $min; return $min + random_int(0, PHP_INT_MAX) / PHP_INT_MAX * ($max - $min); } To give a clear answer on this one: For a full evaluation the reader lacks information: What is this function supposed to do? For floats, the definition of the boundaries matter (that's why it's a parameter for Randomizer::getFloat()). Your function is implemented on the closed interval [0, 1] (i.e. both including 0 and 1). As mentioned in my email a few minutes ago, I consider the ClosedClosed behavior to not be the most useful in the general case, but in your case it might be the correct behavior. Nonetheless, the function is definitely broken: 1. A IEEE 754 double precision float as used by PHP only has 53 Bits of precision, but you generate a random 64 Bit integer. Thus rounding will occur and might cause some values to be returned more often than other. To improve the function you should only generate 53 Bits of randomness (i.e. use 2**53 as the divisor and either 2**53-1 or 2**53 as the dividend). 2. Using the (min + rand * (max - min)) construction will generate biased results (see also my other email). PHP 8.3's Randomizer::getFloat() method uses the γ-section algorithm proposed by Prof. Goualard to generate unbiased results for arbitrary ranges. This algorithm cannot reasonably be implemented in userland, because the necessary "building blocks" (obtaining the next/previous float for a given float) are not available for userland code. The best you can do in PHP 8.2 userland is what Randomizer::nextFloat() does. TLDR: Yes, the function is broken. Best regards Tim Düsterhus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] ext-random: add random_float() ?
Hi On 12/20/22 07:27, Go Kudo wrote: Now that my work is done, I was thinking about a proposal for a sunsetting of existing functions for PHP 8.3 based on the features introduced in ext-random, and I realized that there is no alternative to `lcg_value()`. Essentially, this could be completely replaced by Random\Randomizer::getFloat(), but there are easier `random_int()` and `random_bytes()` functions for ints and strings. The Randomizer may be overkill and complicated for PHP use cases where random number reproducibility is not required in many cases. So, why not add a `random_float(): float` function? This function, like the others, uses CSPRNG and returns a value between 0.0 and 1.0. This behavior is `Closed` `Closed`. Opinions are welcome. I'm not convinced that a random_float() function is a good addition. Especially not with the proposed behavior: 1. Using the (0, 1, ClosedClosed) behavior does neither match Randomizer::nextFloat(), nor Randomizer::getFloat(). 2. I consider the ClosedOpen behavior to be the "correct" default, because the interval can then be cleanly split into equally sized subintervals. But even when random_float() would work like Randomizer::nextFloat() (i.e. (0, 1, ClosedOpen)), I would not consider this a good addition: Users would likely attempt to scale the returned value to arbitrary ranges using the `($min + random_float() * ($max - $min))` construction, instead of using Randomizer::getFloat(). As per Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022 this construction is unsafe, because is is both biased and also may return values outside the expected interval. So random_float() would rather need to behave like Randomizer::getFloat() instead of Randomizer::nextFloat() and then it would not be much simpler than using the Randomizer class directly. I further expect that needing to generate random floats is much rarer than needing to generate random integers or random bytes (for tokens), thus having convenience functions for those two, but not floats is acceptable and keeps the API surface simple, making it easier to document all the gotchas. Users can add convenience wrappers themselves. Best regards Tim Düsterhus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] ext-random: add random_float() ?
2022年12月20日(火) 18:14 Go Kudo : > 2022年12月20日(火) 17:15 Hans Henrik Bergan : > >> btw while we're on the topic, does anyone know if this function gives >> biased results/is-safe or not? i honestly don't know: >> function random_float(float $min, float $max): float >> { >> if ($min > $max) throw new \InvalidArgumentException("min must be >> less than max"); >> if ($min === $max) return $min; >> return $min + random_int(0, PHP_INT_MAX) / PHP_INT_MAX * ($max - >> $min); >> } >> >> >> On Tue, 20 Dec 2022 at 09:06, Hans Henrik Bergan >> wrote: >> > >> > >returns a value between 0.0 and 1.0. >> > >> > wouldn't it be better to follow random_int(int $min, int $max) design? >> eg >> > random_float(float $min, float $max): float >> > >> > On Tue, 20 Dec 2022 at 07:27, Go Kudo wrote: >> > > >> > > Hi Internals. >> > > >> > > Congratulations on the release of PHP 8.2. >> > > I just recently upgraded production PHP from 7.4 to 8.1 :) >> > > >> > > Now that my work is done, I was thinking about a proposal for a >> sunsetting >> > > of existing functions for PHP 8.3 based on the features introduced in >> > > ext-random, and I realized that there is no alternative to >> `lcg_value()`. >> > > >> > > Essentially, this could be completely replaced by >> > > Random\Randomizer::getFloat(), but there are easier `random_int()` and >> > > `random_bytes()` functions for ints and strings. >> > > >> > > The Randomizer may be overkill and complicated for PHP use cases where >> > > random number reproducibility is not required in many cases. >> > > >> > > So, why not add a `random_float(): float` function? This function, >> like the >> > > others, uses CSPRNG and returns a value between 0.0 and 1.0. This >> behavior >> > > is `Closed` `Closed`. >> > > >> > > Opinions are welcome. >> > > >> > > Regards, >> > > Go Kudo >> > > Hi. > > The dangers of generating floating-point random numbers from PHP integer > values are explained in detail in Tim and Joshua's RFC. > > https://wiki.php.net/rfc/randomizer_additions > > I missed it at first too, and was negative about adding > `Randomizer::getFloat()` ... > In general, I think this problem is less noticeable and the absence of the > random_float() function increases the likelihood of incorrect > implementations in userland. > > Regards, > Go Kudo > In the PHP-8.3 current development branch, you can already polyfill as follows However, it is complicated. ```php getFloat($min, $max, $intervalBoundary); } ```
Re: [PHP-DEV] ext-random: add random_float() ?
2022年12月20日(火) 17:15 Hans Henrik Bergan : > btw while we're on the topic, does anyone know if this function gives > biased results/is-safe or not? i honestly don't know: > function random_float(float $min, float $max): float > { > if ($min > $max) throw new \InvalidArgumentException("min must be > less than max"); > if ($min === $max) return $min; > return $min + random_int(0, PHP_INT_MAX) / PHP_INT_MAX * ($max - $min); > } > > > On Tue, 20 Dec 2022 at 09:06, Hans Henrik Bergan > wrote: > > > > >returns a value between 0.0 and 1.0. > > > > wouldn't it be better to follow random_int(int $min, int $max) design? eg > > random_float(float $min, float $max): float > > > > On Tue, 20 Dec 2022 at 07:27, Go Kudo wrote: > > > > > > Hi Internals. > > > > > > Congratulations on the release of PHP 8.2. > > > I just recently upgraded production PHP from 7.4 to 8.1 :) > > > > > > Now that my work is done, I was thinking about a proposal for a > sunsetting > > > of existing functions for PHP 8.3 based on the features introduced in > > > ext-random, and I realized that there is no alternative to > `lcg_value()`. > > > > > > Essentially, this could be completely replaced by > > > Random\Randomizer::getFloat(), but there are easier `random_int()` and > > > `random_bytes()` functions for ints and strings. > > > > > > The Randomizer may be overkill and complicated for PHP use cases where > > > random number reproducibility is not required in many cases. > > > > > > So, why not add a `random_float(): float` function? This function, > like the > > > others, uses CSPRNG and returns a value between 0.0 and 1.0. This > behavior > > > is `Closed` `Closed`. > > > > > > Opinions are welcome. > > > > > > Regards, > > > Go Kudo > Hi. The dangers of generating floating-point random numbers from PHP integer values are explained in detail in Tim and Joshua's RFC. https://wiki.php.net/rfc/randomizer_additions I missed it at first too, and was negative about adding `Randomizer::getFloat()` ... In general, I think this problem is less noticeable and the absence of the random_float() function increases the likelihood of incorrect implementations in userland. Regards, Go Kudo
Re: [PHP-DEV] ext-random: add random_float() ?
btw while we're on the topic, does anyone know if this function gives biased results/is-safe or not? i honestly don't know: function random_float(float $min, float $max): float { if ($min > $max) throw new \InvalidArgumentException("min must be less than max"); if ($min === $max) return $min; return $min + random_int(0, PHP_INT_MAX) / PHP_INT_MAX * ($max - $min); } On Tue, 20 Dec 2022 at 09:06, Hans Henrik Bergan wrote: > > >returns a value between 0.0 and 1.0. > > wouldn't it be better to follow random_int(int $min, int $max) design? eg > random_float(float $min, float $max): float > > On Tue, 20 Dec 2022 at 07:27, Go Kudo wrote: > > > > Hi Internals. > > > > Congratulations on the release of PHP 8.2. > > I just recently upgraded production PHP from 7.4 to 8.1 :) > > > > Now that my work is done, I was thinking about a proposal for a sunsetting > > of existing functions for PHP 8.3 based on the features introduced in > > ext-random, and I realized that there is no alternative to `lcg_value()`. > > > > Essentially, this could be completely replaced by > > Random\Randomizer::getFloat(), but there are easier `random_int()` and > > `random_bytes()` functions for ints and strings. > > > > The Randomizer may be overkill and complicated for PHP use cases where > > random number reproducibility is not required in many cases. > > > > So, why not add a `random_float(): float` function? This function, like the > > others, uses CSPRNG and returns a value between 0.0 and 1.0. This behavior > > is `Closed` `Closed`. > > > > Opinions are welcome. > > > > Regards, > > Go Kudo -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] ext-random: add random_float() ?
>returns a value between 0.0 and 1.0. wouldn't it be better to follow random_int(int $min, int $max) design? eg random_float(float $min, float $max): float On Tue, 20 Dec 2022 at 07:27, Go Kudo wrote: > > Hi Internals. > > Congratulations on the release of PHP 8.2. > I just recently upgraded production PHP from 7.4 to 8.1 :) > > Now that my work is done, I was thinking about a proposal for a sunsetting > of existing functions for PHP 8.3 based on the features introduced in > ext-random, and I realized that there is no alternative to `lcg_value()`. > > Essentially, this could be completely replaced by > Random\Randomizer::getFloat(), but there are easier `random_int()` and > `random_bytes()` functions for ints and strings. > > The Randomizer may be overkill and complicated for PHP use cases where > random number reproducibility is not required in many cases. > > So, why not add a `random_float(): float` function? This function, like the > others, uses CSPRNG and returns a value between 0.0 and 1.0. This behavior > is `Closed` `Closed`. > > Opinions are welcome. > > Regards, > Go Kudo -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
[PHP-DEV] ext-random: add random_float() ?
Hi Internals. Congratulations on the release of PHP 8.2. I just recently upgraded production PHP from 7.4 to 8.1 :) Now that my work is done, I was thinking about a proposal for a sunsetting of existing functions for PHP 8.3 based on the features introduced in ext-random, and I realized that there is no alternative to `lcg_value()`. Essentially, this could be completely replaced by Random\Randomizer::getFloat(), but there are easier `random_int()` and `random_bytes()` functions for ints and strings. The Randomizer may be overkill and complicated for PHP use cases where random number reproducibility is not required in many cases. So, why not add a `random_float(): float` function? This function, like the others, uses CSPRNG and returns a value between 0.0 and 1.0. This behavior is `Closed` `Closed`. Opinions are welcome. Regards, Go Kudo