The Best Random Number Generator

moonlighsunligh

Elite Member
Jr. VIP
Joined
May 1, 2010
Messages
2,442
Reaction score
470
Is there a better function for generating random numbers than this one:


Code:
Dim rdm As New Random(System.DateTime.Now.Millisecond)
Dim number as integer = rdm.[Next](min, max)


What number generator for example the best spinner uses?
 
Have you tried running your method against the same method using a static Random(in your case rdm) ? I am sure it will give you more uniqueness then your current method.
 
Yes.
Code:
System.Security.Cryptography.RandomNumberGenerator.Create()
 
Almost all the random number generates based on static algorithm which always outputs in a similar fashion. To make them effective the random number generator has to be seeded with dynamic values. And in your case you are seeding it with current time. So what's the problem with the current method?
 
The problem with seeding based on time is CPUs process so fast that it can spit out a great amount of data in a millisecond. In turn, you will be using the same seed to produce your random int. To test this, put your code in a for loop and loop it a thousand times while outputting the int as a string so you can see what you get. You'll notice it is a lot of the same values.
 
Yes.
Code:
System.Security.Cryptography.RandomNumberGenerator.Create()

Thanks very much. Trying.



Have you tried running your method against the same method using a static Random(in your case rdm) ? I am sure it will give you more uniqueness then your current method.

I think i got less unique results with that method. I didn't tried to do loop but I will try soon.

The problem with seeding based on time is CPUs process so fast that it can spit out a great amount of data in a millisecond. In turn, you will be using the same seed to produce your random int. To test this, put your code in a for loop and loop it a thousand times while outputting the int as a string so you can see what you get. You'll notice it is a lot of the same values.

But what is solution for this problem? The static random? I have tried a method based on CPU/Memory usage, but it wasn't that good.

Almost all the random number generates based on static algorithm which always outputs in a similar fashion. To make them effective the random number generator has to be seeded with dynamic values. And in your case you are seeding it with current time. So what's the problem with the current method?

I am getting the same number multiple times. Up to 5 times for this sequence 1,2,3,4.
 
Last edited:
Yes.
Code:
System.Security.Cryptography.RandomNumberGenerator.Create()

I wrote a slow function for the implementation, but still I am not sure if results are ok.

Code:
    Public Function Randomize(ByVal min As Integer, ByVal max As Integer) As Integer
        Dim rdm As Integer = max + 1

        Do While rdm = max + 1

            Dim rn(1) As Byte
            System.Security.Cryptography.RandomNumberGenerator.Create.GetNonZeroBytes(rn)
            Dim rdm_big As Integer = Convert.ToInt32(rn(0).ToString)

            For i = min To max
                If rdm_big = i Then
                    rdm = i - 1
                End If
            Next

        Loop

        Return rdm
    End Function



Here are results after a for:
Code:
3
2
2
2
1
4
3
3
2
2
2
4
3
4
1
1
4
4
4
3
4
2
3
2
2
4
1
4
4
1
4
3
4
2
3
3
4
2
3
4
2
 
Last edited:
I wrote a slow (likely 50 x slower than standard random) function for the implementation, but still I am not sure if results are ok.

Here is a function:
Code:
    Public Function Randomize(ByVal min As Integer, ByVal max As Integer) As Integer
        Dim rdm As Integer = max

        Do While rdm = max

            Dim rn(1) As Byte
            System.Security.Cryptography.RandomNumberGenerator.Create.GetNonZeroBytes(rn)
            Dim rdm_big As Integer = Convert.ToInt32(rn(0).ToString)

            For i = min + 1 To max - 1
                If rdm_big = i Then
                    rdm = i
                End If
            Next

        Loop

        Return rdm
    End Function


Here are results:
Code:
3
2
2
2
1
4
3
3
2
2
2
4
3
4
1
1
4
4
4
3
4
2
3
2
2
4
1
4
4
1
4
3
4
2
3
3
4
2
3
4
2

Also better don't seed it inside the loop. Just seed it once and use Next method inside the loop.
 
Do the results seems ok?

This function generates random number between 1 and 255, so if i want to generate random numbers between some other values than 1 and 255 then I have to use a loop.
 
Last edited:
I put this together quick and ran a couple benchmarks. The main problem seems to be the seed, so I tried to use the RNGCryptoServiceProvider to generate a more unique seed. Here are the results:

Using System.DateTime.Now.Millisecond to seed:
1-99
Test 1 = 97 duplicates
Test 2 = 98 duplicates
Avg Execution time: 87ms


1-999
Test 1 = 989 duplicates
Test 2 = 984 duplicates
Avg Execution time: 705ms


1-9999
Test 1 = 9802 duplicates
Test 2 = 9829 duplicates
Avg Execution time: 11400ms


Using your Randomize() function
1-99
Test 1 = 34 duplicates
Test 2 = 34 duplicates
Test 3 = 34 duplicates
Avg Execution time: 131ms


1-999
Test 1 = 751 duplicates
Test 2 = 753 duplicates
Test 2 = 749 duplicates
Avg Execution time: 760ms


1-9999
Test 1 = 9746 duplicates
Test 2 = 9746 duplicates
Test 3 = 9746 duplicates
Avg Execution time: 9100 ms


Using System.Security.Cryptography.RNGCryptoServiceProvider to seed:
1-99
Test 1 = 35 duplicates
Test 2 = 33 duplicates
Test 3 = 40 duplicates
Test 4 = 40 duplicates
Avg Execution time: 71ms


1-999
Test 1 = 376 duplicates
Test 2 = 373 duplicates
Test 3 = 367 duplicates
Avg Execution time: 690ms


1-9999
Test 1 = 3681 duplicates
Test 2 = 3709 duplicates
Test 3 = 3644 duplicates
Avg Execution time: 11425ms


The Function:
Imports
System.Security.Cryptography

Code:
Private Function GetRandom(ByVal iMin As Integer, ByVal iMax As Integer) As Integer        

        Dim iMaxIntLength As Integer = 9

        Dim cChars() As Char = ("1234567890").ToCharArray


        Dim iSize As Integer = iMaxIntLength
        Dim bData(0) As Byte


        Dim Crypt As New RNGCryptoServiceProvider
        Crypt.GetNonZeroBytes(bData)


        iSize = iMaxIntLength
        ReDim bData(iSize - 1)
        Crypt.GetNonZeroBytes(bData)


        Dim sResult As New System.Text.StringBuilder
        For Each bByte As Byte In bData
            sResult.Append(cChars(bByte Mod (cChars.Length - 1)))
        Next


        Dim iRndSeed As Integer = CInt(sResult.ToString)
        Dim rdm As New Random(iRndSeed)
        Dim Num As Integer = rdm.[Next](iMin, iMax)


        Return Num
End Function
 
Last edited:
Thanks. So you still use random function, only it's seed is randomized. I am not sure is that better than using Static random - like bellow:

Code:
Static rdm As System.Random = New System.Random().
 
That is slightly better and much simpler.

1-99
Test 1 = 37 duplicates
Test 2 = 35 duplicates
Avg Execution Time: 12ms


1-999
Test 1 = 345 duplicates
Test 2 = 367 duplicates
Avg Execution Time: 630ms


1-9999
Test 1 = 3688 duplicates
Test 2 = 3688 duplicates
Test 3 = 3662 duplicates
Avg Execution Time: 11294ms
 
Back
Top