[5.8] Fix seeding logic in Arr::shuffle #27861
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The random comparator logic used --
return rand(-1, 1)
-- is not really that random, as it's biased 2:1 in favour of not swapping the two elements.This can be illustrated with the following code, which checks what the first element of a "randomized" array is when using the same logic as
Arr::shuffle()
when a seed is passed (assuming the seeds in this case are randomized as well).Results:
So, when that random logic runs, more than half the time the shuffled array still has the first element in the first position.
Changing the logic to use
return rand(0,1)
helps a bit, but is still biased:I think the basic fix for this is to simply use PHP's
shuffle()
which returns a much more evenly randomized array. If the randomization needs to be seeded, we can just set that before callingshuffle()
(and then set it again afterwards, with a random seed, to prevent later logic in the code from being biased).This PR does this.