How random is random?

I use a random value for a drawing algorithm:

App.Randomizer.InRange(0, 3)

The random value 0-1-2-3 represents left, right, up, down. I left it running for some 20.000 iterations. Statistics:
0: 19468
1: 12703
2: 12662
3: 19328

It looks like the randomizer really loves to spit out 0 or 3 and it dislikes 1 and 2. My drawing algorithm behaves in a predictable pattern (which I don’t like).
How to solve this?

In terms of Xojo code that may give you more randomness, I’m not sure. But in the past I’ve used the random number generator at random.org with success. It’s a json api that generates random numbers seeded by atmospheric radio noise, which is theoretically random in nature to begin with.

It will require your app to be online, though.

https://api.random.org/json-rpc/1/

[quote=278469:@Christian Wheel]In terms of Xojo code that may give you more randomness, I’m not sure. But in the past I’ve used the random number generator at random.org with success. It’s a json api that generates random numbers seeded by atmospheric radio noise, which is theoretically random in nature to begin with.

It will require your app to be online, though.

https://api.random.org/json-rpc/1/[/quote]

I don’t think this will generate more than 1 int per second? I need 4 per second.

How does

App.Randomizer.InRange(0, 2000)  mod 4  

look?

[quote=278472:@Jeff Tullin]How does

App.Randomizer.InRange(0, 2000)  mod 4  

look?[/quote]
Crossed my mind too.

On OS X I’ve always used that:

[code]Function RandomUInt32() As UInt32
Declare Function fopen Lib “/usr/lib/libdl.dylib” (filename As CString, mode As CString) As Ptr
Declare Function fgetc Lib “/usr/lib/libdl.dylib” (stream As Ptr) As Integer
Declare Function fclose Lib “/usr/lib/libdl.dylib” (stream As Ptr) As Integer

Dim value As UInt32 = 0

Dim fp As Ptr = fopen("/dev/random", “r”)

For i As Integer = 0 To 4
value = Bitwise.ShiftLeft(value, 8)
value = Bitwise.BitOr(value, fgetc(fp))
Next

Call fclose(fp)

Return value
End[/code]

I think it could be

App.Randomizer.InRange(-0.5, 3.5)

As it is not possible, maybe:
Dim r As New Random Round(r.Number * 4 - 0.5)

Not sure why you’re seeing that, but I seem to be getting pretty even distribution of those values with this code:

  Dim value As Integer
  Dim counts(3) As Integer
  Const kMax = 200000
  For i As Integer = 1 To kMax
    value = App.Randomizer.InRange(0, 3)
    counts(value) = counts(value) + 1
  Next
  
  TextArea1.Text = ""
  For i As Integer = 0 To counts.Ubound
    TextArea1.AppendText(Str(i) + ": " + Str(counts(i)) + " (" + Str((counts(i) / kMax)*100) + "%)")
    TextArea1.AppendText(EndOfLine)
  Next

Typical results:
0: 50032 (25.016%)
1: 49975 (24.9875%)
2: 50041 (25.0205%)
3: 49952 (24.976%)

In most programming contexts, “random” isn’t truly random, it’s pseudo-random, which is sufficient for most needs, but not sufficient for things like cryptography.

And on Windows we can generate cryptographically random bytes using the crypto API:

[code]Function GetRandomBytes(Count As Integer) As MemoryBlock
Declare Function GetLastError Lib “Kernel32” () As Integer
Declare Function CryptAcquireContextW Lib “AdvApi32” (ByRef Provider as Integer, Container as Integer, ProviderName as WString, _
ProviderType as Integer, Flags as Integer) As Boolean
Declare Function CryptGenRandom Lib “AdvApi32” (Provider As Integer, BufferLen As Integer, Buffer As Ptr) As Boolean
Declare Function CryptReleaseContext Lib “AdvApi32” (Provider As Integer, Reserved As Integer) As Boolean

Const MS_DEF_PROV = “Microsoft Base Cryptographic Provider v1.0”
Const PROV_RSA_FULL = 1
Const NTE_BAD_KEYSET = &h80090016
Const CRYPT_VERIFYCONTEXT = &hF0000000

Dim baseprovider, lasterr As Integer
If Not CryptAcquireContextW(baseprovider, 0, MS_DEF_PROV, PROV_RSA_FULL, 0) Then
lasterr = GetLastError
If lasterr = NTE_BAD_KEYSET And Not CryptAcquireContextW(baseprovider, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then
lasterr = GetLastError
Dim err As New RuntimeException
err.ErrorNumber = lasterr
Raise err
End If
End If

Dim mb As MemoryBlock
Try
mb = New MemoryBlock(Count)
If Not CryptGenRandom(baseprovider, mb.Size, mb) Then
lasterr = GetLastError
Dim err As New RuntimeException
err.ErrorNumber = lasterr
Raise err
End If
Finally
Call CryptReleaseContext(baseprovider, 0)
End Try
Return mb
End Function
[/code]

Or you can use the Crypto API for the exact same thing
http://documentation.xojo.com/index.php/Crypto

[quote=278468:@Alexander van der Linden]I left it running for some 20.000 iterations. Statistics:
0: 19468
1: 12703
2: 12662
3: 19328
[/quote]
I assume that you must have let it run for a lot more than 20,000 iterations. The totals add up to 64161. The thing about randomness is that something like this can easily happen. If the frequencies had come out exactly the same then I would be a lot more suspicious. I can’t speak for the current Xojo RNG, but I’ve used the old Realbasic RNG for some statistically critical calculations, and found that it was acceptable up to a few million numbers. After that, it started to exhibit some skewing of the numbers. So, I later coded my own RNG based on some published well proven algorithms. It would be nice if the Xojo documentation would indicate what algorithm is used.

For what it’s worth, I don’t see it here either. Looks ok to me with either 1000, 60.000 or 1M iterations:

0 = 249883
1 = 250385
2 = 249560
3 = 250173

0 = 249408
1 = 250793
2 = 250033
3 = 249767

0 = 250055
1 = 250739
2 = 249378
3 = 249829

It is TrueCrypt which uses the mouse movements to create a truly random key.

Upon the same principle, you could record all mouse moves as the app runs, and then use the condensed values of MouseX and MouseY as seed. By condensed, I mean you filter only the results that are different from the previous one as to have only a series of different numbers.

Do a simple x-y plot where you treat random-even as x coordinate and random-odd as y coordinate. If you see clouds then your random isn’t random enough.

Good idea Beatrix, except I used a single value to derive x/y.

I created a project here:

https://dl.dropboxusercontent.com/u/26920684/Randomness.xojo_binary_project

Actually, in an x-y plot you should see clouds or clusters if the data is random. Google “clustering illusion” to see the mathematical basis for this. Random is hard.

Dennis

[quote=278695:@Dennis Hoskins]Actually, in an x-y plot you should see clouds or clusters if the data is random. Google “clustering illusion” to see the mathematical basis for this. Random is hard.

Dennis[/quote]

no, you should NOT see clouds or clusters… because if you do, then it means the algorithm is "favoring " those areas. a truly random generator should create a uniform scatter of x,y coordinates indicting that it is NOT favoring any particular value.

the wikipedia example is attempting to prove true randomness using a pseudo generator… you can’t do that. and “prove” that clouds and clumps are indictivate of true random numbers… Its like using red paint to prove that blue is the perfect color

Hold on! Excuse me but I have to admit I’m wrong :(. I check if the random value is the opposite of the previous one to control the direction, and if so I need a new random.

Without this check the statistics show a normal pattern… Sorry for upsetting you all.

I’m not familiar with pseudo-random number generation and the code predates me by a long while. However, I can tell you what the code for the Random class claims to be doing.

The comment at the top of the file states that “the code was adapted from Algorithms in C++ (second edition) by Robert Sedgwick.” The code relating to gaussian distributions refers to the Ziggurat algorithm and was “adapted from code in a 2005 paper by Jurgen A. Doornik.”