Sunny Chakraborty (B|T), started a page about top 12 things on his mind and since the last one looked a little easy I took a shot at it.

12. **Better Get-Random** for small ranges (0-1000). Test for randomness of Get-Random.

Oh boy! was I wrong. What started as an exercise to generate small random sets led me around Wikipedia pages and finally showed me the Fisher-Yates Shuffle.

This was my first solution. And it absolutely sucks, generates loads of zeros and the reason why this happens is not due to the lack of the randomness of the running ticks but the fact that we modulus the result with 1000 to get the value into our range of interest. The basic problem with this is that we can fix it but; at a cost to speed and we may also need a cache the intermediate states to guarantee uniqueness in the set.

Function Get-SmallRandom
{
$procArch = $env:PROCESSOR_ARCHITECTURE
if($env:PROCESSOR_ARCHITECTURE -match “\d{2}$”){$procArch = $Matches[0]}
if($procArch -eq 64){
[Int](((Get-Date).Second * (Get-Date).Millisecond * (Get-Date).Ticks) / ([Int64]::MaxValue + 1))
}elseif($procArch -eq 32){
[Int]((((Get-Date).Ticks/(Get-Date).Millisecond)/([Int32]::MaxValue + 1.0))/1000)
}else{
[Int]((((Get-Date).Ticks/(Get-Date).Millisecond)/([Int32]::MaxValue + 1.0))/1000)
}
}
$a = 1..1000 | %{Get-SmallRandom}
$b = 1..1000 | %{Get-SmallRandom}
Compare-Object -ReferenceObject $a -DifferenceObject $b -ExcludeDifferent

Then it struck me that I may have approached the problem in a wrong direction. Given a set of 1000 numbers, how do I shuffle the set in an unbiased way so that it has the appearance of a randomly generated set? Cool, so how the hell do I do it; the obvious solution was to pick two random numbers less than size of the array the swap the numbers. But, I was not sure if this was such a good idea and started looking if there were any algorithms that did this and surely there is, the ‘Fisher Yates shuffle’. It is easy to implement and works great. So, here is my crack at it:

Function Get-ShuffledArray
{
param(
[Array]$gnArr
)
$len = $gnArr.Length;
while($len)
{
$i = Get-Random ($len --);
$tmp = $gnArr[$len];
$gnArr[$len] = $gnArr[$i];
$gnArr[$i] = $tmp;
}
return $gnArr
}

Not sure if this is an acceptable solution for what Sunny was looking for but, it was a wonderful learning experience. As always, working with PowerShell is fun.

### Like this:

Like Loading...

*Related*

## Leave a Reply