Re: [PHP-DEV] ext-random: add random_float() ?

2023-01-10 Thread Go Kudo
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() ?

2022-12-29 Thread Tim Düsterhus

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() ?

2022-12-29 Thread 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

--
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 Thread Go Kudo
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 Thread 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


Re: [PHP-DEV] ext-random: add random_float() ?

2022-12-20 Thread 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

-- 
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 Thread Hans Henrik Bergan
>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() ?

2022-12-19 Thread Go Kudo
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