Results 1 to 3 of 3

Thread: A More Random Random Class

Threaded View

  1. #1

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    A More Random Random Class

    C# version here.

    The .NET Framework includes the System.Random class, whose job it is to generate random numbers. It does so using a sequence based on a seed value, which is based on the system time by default. There are numerous possible seeds and predicting the exact time that a Random object will be created is not easy. That, coupled with the fact that the distribution of numbers generated by the sequence satisfies various statistical requirements for randomness, means that the Random class is quite suitable for most of your random number needs.

    The main issue with the Random class is that, given a particular seed, the sequence will always produce the same numbers. That can actually be good for some testing scenarios but it does mean that the results could be manipulated. Where very high levels of unpredictability are required, the Random class is not suitable.

    I've seen a number of people use various methods to generate more random random numbers. That's not really necessary though. The .NET Framework also includes the System.Security.Cryptography.RNGCryptoServiceProvider class for generating random numbers. It's output is sufficiently random for use in cryptography, so there's really no need for anything more random than that.

    One issue with the RNGCryptoServiceProvider class, though, is that it populates Byte arrays with random values. That's not always completely convenient though, as the most common need in applications is a random Integer within a specific range. The Random class is nice and easy to use in that scenario, thanks to its Next method. What if we could combine the ease of use of the Random class with the increased randomness of the RNGCryptoServiceProvider class?

    As it happens, we can. The Random class has a Protected method named Sample that generates a Double in the range 0.0 <= x < 1.0. The result of that method is then used in the other methods to generate Integers in a range. We can define our own class that inherits Random and overrides that Sample method to use RNGCryptoServiceProvider internally. Here's one I prepared earlier:
    vb.net Code:
    1. Imports System.Security.Cryptography
    2.  
    3. ''' <summary>
    4. ''' Represents a random number generator, a device that produces a sequence of numbers that meet cryptographic requirements for randomness.
    5. ''' </summary>
    6. ''' <remarks>
    7. ''' Seed values are meaningless because this class uses a cryptographic service provider internally rather than a pseudo-random sequence.
    8. ''' </remarks>
    9. Public Class CryptoRandom
    10.     Inherits Random
    11.     Implements IDisposable
    12.  
    13.     ''' <summary>
    14.     ''' The internal random number generator.
    15.     ''' </summary>
    16.     Private ReadOnly rng As New RNGCryptoServiceProvider
    17.  
    18.     ''' <summary>
    19.     ''' Returns a random number between 0.0 and 1.0.
    20.     ''' </summary>
    21.     ''' <returns>
    22.     ''' A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
    23.     ''' </returns>
    24.     ''' <remarks>
    25.     ''' Uses a cryptographic service provider internally rather than a pseudo-random sequence.
    26.     ''' </remarks>
    27.     Protected Overrides Function Sample() As Double
    28.         Dim data(7) As Byte
    29.         Dim number As ULong
    30.  
    31.         Do
    32.             'Get 8 random bytes.
    33.             rng.GetBytes(data)
    34.  
    35.             'Convert the bytes to an unsigned 64-bit number.
    36.             number = BitConverter.ToUInt64(data, 0)
    37.         Loop While number = ULong.MaxValue 'The result must be less than 1.0
    38.  
    39.         'Divide the number by the largest possible unsigned 64-bit number to get a value in the range 0.0 <= N < 1.0.
    40.         Return number / ULong.MaxValue
    41.     End Function
    42.  
    43. #Region "IDisposable Support"
    44.  
    45.     Private disposedValue As Boolean ' To detect redundant calls
    46.  
    47.     ' IDisposable
    48.     Protected Overridable Sub Dispose(disposing As Boolean)
    49.         If Not Me.disposedValue Then
    50.             If disposing Then
    51.                 'Dispose the underlying cryptographic random number generator.
    52.                 rng.Dispose()
    53.             End If
    54.         End If
    55.  
    56.         Me.disposedValue = True
    57.     End Sub
    58.  
    59.     ' This code added by Visual Basic to correctly implement the disposable pattern.
    60.     Public Sub Dispose() Implements IDisposable.Dispose
    61.         ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
    62.         Dispose(True)
    63.         GC.SuppressFinalize(Me)
    64.     End Sub
    65.  
    66. #End Region
    67.  
    68. End Class
    You can create an instance of that class and use it in pretty much exactly the same way as you would a Random object. The only difference is that you will need to call its Dispose method when you're done, in order to dispose the internal RNGCryptoServiceProvider object. Sample usage:
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     Private ReadOnly rng As New CryptoRandom
    4.  
    5.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    6.         'Generate 10 random numbers.
    7.         Dim numbers(9) As Integer
    8.  
    9.         For i = 0 To numbers.GetUpperBound(0)
    10.             'Generate numbers in the range 0 <= n <= 1000
    11.             numbers(i) = rng.Next(1001)
    12.         Next
    13.  
    14.         MessageBox.Show(String.Join(Environment.NewLine, numbers),
    15.                         "10 Random Numbers")
    16.     End Sub
    17.  
    18.     Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    19.         rng.Dispose()
    20.     End Sub
    21.  
    22. End Class
    Attached Files Attached Files
    Last edited by jmcilhinney; May 22nd, 2013 at 03:48 AM.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width