Results 1 to 11 of 11

Thread: [RESOLVED] Random

  1. #1

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Resolved [RESOLVED] Random

    Just for the heck of it I am buying this true random generator.

    https://www.amazon.com/TrueRNG-V3-Ha.../dp/B01KR2JHTA

    The device sends bytes over the comport that are random.

    To get a head start I thought I would try and mimic what the Random class does. At the core of Random is the .Sample method. And right from go I am confused.

    How do you create a Double greater than or equal to 0 and less than one from 8 random bytes? I have some code that appears to work but is slow, 6 seconds to produce 1,000,000 Doubles.

    Code:
                '   Significand or mantissa 	0-51
                '   Exponent 52 - 62
                '   Sign (0 = Positive, 1 = Negative) 	63
                '                     8000000000000
                Me._methodLock.WaitOne() 'for thread safety
                Dim rv As Double = Double.NaN
                Const MantMsk As Long = &HFFFFFFFFFFFFFL
                Const ExpMsk As Long = &H7FF0000000000000L
                Const Mask As Long = MantMsk Or ExpMsk 'negative numbers not possible with this mask
                Dim L As Long = Long.MinValue
                If Me.WaitForBytes(8) Then 'wait for there to be at least 8 bytes in the com buffer
                    Dim byteVal As New List(Of Byte)
                    Do While byteVal.Count < 8 'get eight bytes from the com buffer
                        Dim b As Byte
                        If Me.buf.TryDequeue(b) Then
                            byteVal.Add(b)
                        End If
                    Loop
                    ' L is a long
                    L = Mask And BitConverter.ToInt64(byteVal.ToArray, 0)
                    Do
                        Dim ct As Integer = 0
                        rv = BitConverter.ToDouble(BitConverter.GetBytes(L), 0)
                        '1.#QNAN
                        If Double.IsInfinity(rv) OrElse
                                Double.IsNaN(rv) OrElse
                                Double.IsNegativeInfinity(rv) OrElse
                                Double.IsPositiveInfinity(rv) Then
                            L = L Xor Long.MinValue
                        ElseIf rv >= 0.0R AndAlso rv < 1.0R Then '
                            Exit Do 'success
                        End If
                        ct += 1
                        Dim foo As Long = L
                        Dim exp As Long = (foo And ExpMsk) >> 52
                        exp = (exp << 51) And ExpMsk
                        foo = (foo And MantMsk)
                        foo = foo Or exp
                        L = foo
                    Loop
                Else
                    'todo
                    Stop
                End If
    Until I get the device I am filling the comport buffer with random bytes using the Random class.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,669

    Re: Random

    For what its worth, here is the source code for Random: https://referencesource.microsoft.co...stem/random.cs

    It is using the Linear Congruential Generator algorithm to initialize the seed. That's about as far down the rabbit hole I got.

    Random is a topic similar to infinity for me. It's really cool but gets way over my head way too quickly.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,227

    Re: Random

    Note that the Random class only produces pseudorandom numbers. They appear random to the casual observer but the sequence is predictable if you know the initial conditions. The RandomNumberGenerator class provides numbers that are sufficiently random for cryptographic use.

  4. #4
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Random

    Code:
    x = BitConverter.Touint32(byteVal.ToArray, 0)
    y = BitConverter.Touint32(byteVal.ToArray, 4)
    rv = x / y
    add code to care about the edge cases (y=0 and x=y if you do not want 1 as possible result)

    edit: of course you need to exchange x and y if x > y so that y is always bigger or equal x. But i guess you get the point.
    Last edited by digitalShaman; Dec 3rd, 2023 at 04:05 AM.

  5. #5

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Re: Random

    Quote Originally Posted by digitalShaman View Post
    Code:
    x = BitConverter.Touint32(byteVal.ToArray, 0)
    y = BitConverter.Touint32(byteVal.ToArray, 4)
    rv = x / y
    add code to care about the edge cases (y=0 and x=y if you do not want 1 as possible result)

    edit: of course you need to exchange x and y if x > y so that y is always bigger or equal x. But i guess you get the point.
    Thought about something like this. I'll give it a try tomorrow. The device should be here Wednesday. Thanks!
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  6. #6

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Re: Random

    This is where I am so far, still waiting on the actual device. I have ran some test for verification, see end.

    Here is a question, could I use Int16 instead of Int32? Or should I use Int64?

    Code:
            ''' <summary>
            ''' returns a double greater than or equal to 0 and less than 1
            ''' </summary>
            ''' <returns>Double</returns>
            ''' <remarks></remarks>
            Private Function Sample() As Double
                Dim rv As Double = Double.NaN
                Dim int1 As Integer
                Dim int2 As Integer
                Dim byts() As Byte
                int1 = 0
                int2 = 0
                'create two integers
                Do While int1 = int2
                    byts = Me.GetBytes(4) 'get 4 bytes from com buffer
                    'use loop because .GetBytes might not return 4 bytes
                    For idx As Integer = 0 To byts.Length - 1
                        int1 = int1 << 8
                        int1 = int1 Or byts(idx)
                    Next
                    byts = Me.GetBytes(4) 'get bytes from com buffer
                    For idx As Integer = 0 To byts.Length - 1
                        int2 = int2 << 8
                        int2 = int2 Or byts(idx)
                    Next
                    'turn off sign
                    int1 = int1 And Integer.MaxValue
                    int2 = int2 And Integer.MaxValue
                    If int1 = int2 Then
                        int1 = int1 Xor Integer.MaxValue
                    End If
                Loop
    
                If int1 > 0 OrElse int2 > 0 Then
                    If int1 > int2 Then
                        rv = int2 / int1
                    Else
                        rv = int1 / int2
                    End If
                Else
                    Stop 'todo ??????
                End If
                'does this happen?????
                If Double.IsInfinity(rv) OrElse
                        Double.IsNaN(rv) OrElse
                        Double.IsNegativeInfinity(rv) OrElse
                        Double.IsPositiveInfinity(rv) Then
    
                    Stop 'todo
                End If
    
                Return rv
            End Function
    I ran 5,000,000 iterations of:

    Heads / Tails and it was 50 / 50
    Two dice and it matched the total distribution
    Created integers and counted digits in the answer
    -- ran the same thing against the System.Random and matched

    As you can see there are some questions in the code that I will resolve when I get the device.

    Is anyone interested about the device?


    Results of significant digit count

    System.Random

    1 0.0000 %
    2 0.0000 %
    3 0.0000 %
    4 0.0004 %
    5 0.0045 %
    6 0.0412 %
    7 0.4186 %
    8 4.1937 %
    9 41.8918 %
    10 53.4497 %

    TRNG

    1 0.0000 %
    2 0.0000 %
    3 0.0000 %
    4 0.0004 %
    5 0.0038 %
    6 0.0428 %
    7 0.4186 %
    8 4.1972 %
    9 41.8843 %
    10 53.4530 %
    Last edited by dbasnett; Dec 5th, 2023 at 01:13 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  7. #7
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Random

    A warning: I am not so sure anymore that this approach will generate evenly distributed numbers.
    For example the result of Int.max-1 / int.max will only be possible with these exact two numbers while a result of 0.5 is generated by multiple number combinations such as 1/2, 2/4, etc.

  8. #8

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Re: Random

    Quote Originally Posted by digitalShaman View Post
    A warning: I am not so sure anymore that this approach will generate evenly distributed numbers.
    For example the result of Int.max-1 / int.max will only be possible with these exact two numbers while a result of 0.5 is generated by multiple number combinations such as 1/2, 2/4, etc.
    I was going to try to figure out the distribution but realized I didn't understand a lot of the code I looked at.

    I did let the device run overnight turning on two pixels per second in a blank image.

    Result:

    Name:  TrueRNG.jpg
Views: 175
Size:  124.2 KB
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  9. #9

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Re: Random

    Quote Originally Posted by digitalShaman View Post
    A warning: I am not so sure anymore that this approach will generate evenly distributed numbers.
    For example the result of Int.max-1 / int.max will only be possible with these exact two numbers while a result of 0.5 is generated by multiple number combinations such as 1/2, 2/4, etc.
    Haven't tested with the TRNG hardware but this works with Random.

    Code:
        Private prng As New Random
        Private gtONE As ULong = 0UL
        Private Function Sample() As Double
            Dim rv As Double = 0.0#
            'Bytes
            '7   Mantissa	0-51 
            '2   Exponent	52-62  0 - 1022
            Dim byts(8) As Byte '9 bytes
            prng.NextBytes(byts) ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<REPLACE with TRNG get
            Dim exp As Long = 0L
            If byts.Length > 1 Then
                'create Exponent
                exp = byts(0)
                exp = exp << 8
                exp = exp Or byts(1)
                ' keep 10 bits only
                exp = exp And &H3FFL ''this mask &H1FFL  stops >= 1.0 '  
            End If
            If exp >= 1023 Then exp -= 1L
            '  If exp >= 1000 Then exp -= 23L ' but some exp >= 1000 are good
            '  e.g. 0.46678963503161  exp = 1021
    
            exp = exp << 52 'position Exponent
            Dim L As Long = 0L
            For x As Integer = 2 To byts.Length - 1 'create Mantissa
                L = L << 8
                L = L Or byts(x)
            Next
            L = L And SignificandMSK '52 bits only
            L = L Or exp 'add Exponent
            rv = BitConverter.Int64BitsToDouble(L)
            If rv >= 1.0# Then
                rv = rv / Math.PI
                Me.gtONE += 1UL
            End If
            If rv >= 1.0# Then
                'todo
                Stop
            End If
            Return rv
        End Function
    Last edited by dbasnett; Dec 10th, 2023 at 07:56 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  10. #10

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Angry Re: Random

    Great, just great. So I have been looking at the source of .Random. In it I find this.
    Code:
        public virtual int Next(int maxValue) {
              if (maxValue<0) {
                  throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue"));
              }
              Contract.EndContractBlock();
              return (int)(Sample()*maxValue);
          }
    So my new .Sample apparently does a broader range.

    8.7253577634378e-280
    5.10351429655486e-168
    7.66905992703698e-225
    1.63228078929909e-137
    4.81252807881766e-185
    1.0806761131728e-158
    6.00381557186564e-135
    8.91585051435279e-183
    6.63151599550507e-162
    1.81935382013397e-138
    2.28408466952934e-71
    2.78949524958343e-283
    2.43364313225461e-265
    3.82096161246175e-165
    4.3831210318899e-140
    9.54907848369536e-123

    4.76116207454203e-45
    0.00277009731881507
    6.20504061442252e-205
    2.4889082471918e-20
    8.67933824628034e-253
    6.59549839909513e-49
    8.6448449726707e-288
    7.30206483116989e-111
    3.26052204441488e-102
    3.3667687899405e-128
    1.70358091448857e-77
    3.67136132927937e-269
    3.41397071621818e-15
    3.43220382872364e-155
    2.58852200039163e-64
    3.55377161269553e-68

    3.16103698589824e-189
    1.34132824028634e-196
    4.7029016099803e-18
    1.3649258957631e-292
    8.71277705385738e-183
    5.49958265719597e-29
    4.36150273910638e-175
    7.54537044298667e-15
    6.01228626236831e-65
    6.82407168351128e-05
    2.00518986766811e-122
    2.00214876288474e-104
    6.97052809694117e-110
    1.07402982506738e-62
    1.75113941553553e-190
    8.01532381965969e-278

    5.87034189846368e-30
    4.39118219624152e-193
    1.12863560347159e-72
    4.07807280569997e-183
    1.33797727986362e-152
    8.77861478648681e-271
    6.52053556928832e-197
    1.17493728755003e-116
    6.11487766561578e-74
    1.12273389231186e-176
    3.58183377297382e-181
    2.02060585288374e-236
    3.29833187060158e-233
    4.51661450924151e-149
    3.40411805343502e-15
    1.31057074649206e-126
    Too broad to do this,

    Code:
            Dim rv As Double = Me.Sample() * maxValue
            rv = CInt(Math.Truncate(smpl))
            Return rv
    Damn, damn, ....
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  11. #11

    Thread Starter
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,732

    Re: Random

    I have resolved this with code based on System.Random. Left the original as a conditional.

    Code:
        Const MBIG As Double = 1.0# / Integer.MaxValue
        Private Function ISample() As Double
            Dim rv As Double = 0
    #Const Methd = "1" ' "2"
            Dim I1 As Integer = Me.Next 'get random integer between 0 and Integer.MaxValue
    #If Methd = "1" Then
            rv = I1 * MBIG
    #ElseIf Methd = "2" Then
            Dim I2 As Integer = Me.Next
            If I1 > I2 Then
                rv = I2 / I1
            ElseIf I2 > I1 Then
                rv = I1 / I2
            ElseIf I1 <> Integer.MaxValue Then
                rv = I2 / (I1 + 1)
            Else
                rv = (I2 - 1) / I1
            End If
    #End If
            Return rv
        End Function
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

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