I was looking at creating randomness again and came across: RNGCryptoServiceProvider
Specifically, System.Security.Cryptography.RNGCryptoServiceProvider
Most of what I read said that this is the best way to generate random values.
From what I can tell, it is designed to generate a random byte. So, it will fill a byte array with random values between 1 and 255. This is the behavior I saw when testing in PowerShell.
Most of the examples I found online of how to use this to generate a random selection out of an array of options is to do something like:
----------------------------------------------------
# Create character array
$chars = "qwertyuiopasdfghjklzxcvbnm1234567890"
# Create a byte array with one place in it
$byte = New-Object System.Byte[] 1
# Create random number generator
$rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
# Fill our byte array with a random value (between 1 and 255), giving us a single random byte value
$rng.GetBytes($byte)
# Get and integer of this value
$rnd = $byte[0] -as [int]
# Generate an integer to be used as an index value in our character array
$int = ($rnd % $($chars.Length))
# Get your random character
$chars[$int]
----------------------------------------------------
While this works fine, I got to wondering if this method will favor some characters in our character array over others. For example, look at this output. I am executing the command "1..255 | % {$_ % $chars.Length} | group" which...
- counts from 1 to 255, sending each number down the pipeline
- for each number, it calcs <number> MODULO <CharArrayLength>
- it then groups my results
*************
§ Derek-D620 {C:\s\u} 1..255 | % {$_ % $chars.Length} | group
Count Name Group ----- ---- ----- 8 1 {1, 1, 1, 1...} 8 2 {2, 2, 2, 2...} 8 3 {3, 3, 3, 3...} 7 4 {4, 4, 4, 4...} 7 5 {5, 5, 5, 5...} 7 6 {6, 6, 6, 6...} 7 7 {7, 7, 7, 7...} 7 8 {8, 8, 8, 8...} 7 9 {9, 9, 9, 9...} 7 10 {10, 10, 10, 10...} 7 11 {11, 11, 11, 11...} 7 12 {12, 12, 12, 12...} 7 13 {13, 13, 13, 13...} 7 14 {14, 14, 14, 14...} 7 15 {15, 15, 15, 15...} 7 16 {16, 16, 16, 16...} 7 17 {17, 17, 17, 17...} 7 18 {18, 18, 18, 18...} 7 19 {19, 19, 19, 19...} 7 20 {20, 20, 20, 20...} 7 21 {21, 21, 21, 21...} 7 22 {22, 22, 22, 22...} 7 23 {23, 23, 23, 23...} 7 24 {24, 24, 24, 24...} 7 25 {25, 25, 25, 25...} 7 26 {26, 26, 26, 26...} 7 27 {27, 27, 27, 27...} 7 28 {28, 28, 28, 28...} 7 29 {29, 29, 29, 29...} 7 30 {30, 30, 30, 30...} 7 31 {31, 31, 31, 31...} 7 32 {32, 32, 32, 32...} 7 33 {33, 33, 33, 33...} 7 34 {34, 34, 34, 34...} 7 35 {35, 35, 35, 35...} 7 0 {0, 0, 0, 0...}
*****************
As you can see, some results come up more than others. Specifically (in this case) 1, 2, and 3 will show up more often than the rest of the results. So, looking at my CharArray, the letters w, e, and r will show up more often in my result sets. I am thinking that, to create an environment that does not favor any particular subset of our character array, I need my 'byte' value to be evenly divisible by my charArray length. So, rather than using a max possible value of 255, my max possible value needs to be the largest value where "maxValue MODULO charArrayLength = 0"
Ugh!
And, this doesn’t take into account the possibility that my max value could be larger than 255, in which case this formula just spits out 255.
Ugh! Ugh!

