Understanding the nature of Randomness and Testing Delphi’s Random function

Randomness is a key concept in Science and Philosophy. It has got a mathematical form, physical behaviour and philosophical mystery. I have studied this concept in my MD thesis under the title; “The Randomness Problem in 20th Century Thought”. I have come up several scientific and philosophical results, however I want to discuss a particular aspect of the problem, the behavioral form (physical mathematics) of randomness here.

The random distributions (random sets) have their own nature, they tend to obey a statistical discipline if it is really natural. In computer science there is a strong distinction between the true random numbers and the pseudo random numbers. The true ones come from nature as the result of a dice playing and the pseudo ones are results of logical/mathematical processes. So mostly the ones generated in computers are pseudo numbers as a result of a mathematical formula. True randomness have got an order, if the items in the random sets have got an equal chance of existence, the share also must be close to equal with a minor error. This error gets even smaller when the set grows. Think of a man throwing a coin. If he throws twice, the result may be one of this patterns; [TH, HT, TT, HH]. In this result set, Head and Tail shares the existence equally in a 50% possibility. So in %50 of the cases the share is not equal; and that means the error is %50. Is it really minor? 🙂 So you can see here that if we make more throwing the possibility of error will get smaller. You can calculate the quantity of the error with the \frac{\sqrt{n}}{2} formula where n is the number of throwing.

When you calculate the error for each n and plot it on a graph, you will see a well-know statistical pattern which is called the normal curve. The ideal normal curve can be drawn with the formula \frac{1}{\sqrt{2\pi}}.e^{-x^{2}/2}.

This normal curve the behavioural pattern of the nature. If you throw dice million times you can draw this graph. This graph is neither physical not mathematical. It means there is no rational base for the normal curve either in math or physics. Mark Kac, an important modern mathematician, makes a methodic discussion on the mystery of the behavioral pattern of random sets in his article about randomness problem[1].He declares that a random set is true if only it behaves according to this normal curve pattern and suggests a coin toss experiment with huge numbers to be able to see the graph as a result.

So in this article; we will follow Mark Kac, and make experiments to see if random generators arround us are natural or not. The most nobel way to test randomness is to observe particle behaviours under atomic level which is the ultimate kingdom of randomness. An easier but not easy way is to throw dice million and million times to see the graph. As a computer programmer I will chouse my easy way; programming in Delphi, both to see the natural randomness and Delphi’s randomness. To test randomness in its natural way, I can’t trust un the Delphi’s Random function (or any computer’s) as it is stated in the Delphi’s reference, so I need physical data from the nature itself. For this I will use the random.org website which generates random numbers using the atmospherical noise.

First of all I will code a class named TOnlineRandomizer which will connect to Random.org url based service and get random numbers. Note that Random.org free web services are limited by generated bits, however the free bits are enough to get an observable result.  Here is the class header for TOnlineRandomizer.

TOnlineRandomizer = class(TObject)
private
  FResultList: TStringList;
  FIntUrlPattern:String;
  FDecUrlPattern:String;
  FSettings:TFormatSettings;
  Procedure GetResultsFromWeb(qUrl:String);
  function GetRandomInteger(Index: Integer): Integer;
  function GetRandomDecimal(Index: Integer): Single;
  function GetCount: Integer;
  function GetRandomString(Index: Integer): String;
public
  Constructor Create;
  Destructor Destroy;override;
  Procedure GetRandomIntegers(iMin,iMax,iCount:Integer);
  Procedure GetRandomDecimals(dPrecission,dCount:Integer);
  Procedure GetPseudoRandomIntegers(iMin,iMax,iCount:Integer);
  Procedure GetPseudoRandomDecimals(dPrecission,dCount:Integer);
  Property Count:Integer read GetCount;
  Property RandomInteger[Index:Integer]:Integer read GetRandomInteger;
  Property RandomDecimal[Index:Integer]:Single read GetRandomDecimal;
  Property RandomString[Index:Integer]:String read GetRandomString;
end;

The class has got to execution procedures, GetRandomIntegers which calls the integer generator service of Random.org, and GetRandomDecimals which calls the fraction generator service of Random.Org. After the calling any of the execution you can reach the results using the array properties, RandomInteger to get the item as integer, RandomDecimal to get the item as float and RandomString to get the item as string. In both generation functions you should give a count, and after the results the readonly count property will equal to your count request or less in case of any limitation. The results are received from Random.org as text file, so they are stored in a TStringlist, you should know that reaching the numbers through RandomInteger or RandomDecimal property will cost an additional conversion time and risk, so if you will just show the numbers on the screen you can use the RandomString property which gives the received item from the list with no conversion.

A typical usage of the class may be like this.

procedure TForm1.Button1Click(Sender: TObject);
var rndGen:TOnlineRandomizer;
    i: Integer;
begin
  rndGen := TOnlineRandomizer.Create;
  rndGen.GetRandomDecimals(20,100);
  for i  := 0 to rndGen.Count-1 do
    Memo1.Lines.Add(rndGen.RandomString[i]);
  rndGen.Free;
end;

The TOnlineRandomizer class has got a private method GetResultsFromWeb, in which it receives the numbers from Random.org using the formatted url with the parameters of GetRandomIntegers/GetRandomDecimals. The results are CR+LF separated so can be directly loaded to a TStringList – FResultList which is created in the constructor, destroyed in the destructor and will store the random numbers during the session. The url formats are arranged according to the interface of Random.Org, but you can direct to request to any other online randomizer service by changing the url formats in the constructor.

constructor TOnlineRandomizer.Create;
begin
  inherited Create;
  FIntUrlPattern := 'http://www.random.org/integers/'+
                    '?min=%d&max=%d&num=%d&col=1&base=10&format=plain&rnd=new';
  FDecUrlPattern := 'http://www.random.org/decimal-fractions/'+
                    '?dec=%d&num=%d&col=1&format=plain&rnd=new';
  FResultList := TSTringList.Create;
  FSettings := TFormatSettings.Create;
  FSettings.DecimalSeparator := '.';
end;

destructor TOnlineRandomizer.Destroy;
begin
  FResultList.Free;
  inherited;
end;

procedure TOnlineRandomizer.GetRandomDecimals(dPrecission, dCount: Integer);
var qUrl: String;
begin
  qUrl := Format(FDecUrlPattern,[dPrecission, dCount]);
  Self.GetResultsFromWeb(qUrl);
end;

procedure TOnlineRandomizer.GetRandomIntegers(iMin, iMax, iCount: Integer);
var qUrl: String;
begin
  qUrl := Format(FIntUrlPattern,[iMin,iMax,iCount]);
  Self.GetResultsFromWeb(qUrl);
end;

procedure TOnlineRandomizer.GetResultsFromWeb(qUrl: String);
var httpObj:TIdHttp;
    FResultStream: TMemoryStream;
begin
  FResultStream := TMemoryStream.Create;
  httpObj := TIdHttp.Create(nil);
  httpObj.Get(qUrl,FResultStream);
  FResultStream.Position := 0;
  FResultList.LoadFromStream(FResultStream);
  FResultStream.Free;
  httpObj.Free;
end;

In addition to these main methods, we have some other methods for the read only properties as below.

function TOnlineRandomizer.GetCount: Integer;
begin
  Result := FResultList.Count;
end;

function TOnlineRandomizer.GetRandomDecimal(Index: Integer): Single;
begin
  result := StrToFloat(FResultList[Index],fSettings);
end;

function TOnlineRandomizer.GetRandomInteger(Index: Integer): Integer;
begin
  result := StrToInt(FResultList[Index]);
end;

function TOnlineRandomizer.GetRandomString(Index: Integer): String;
begin
  Result := FresultList[Index];
end;

In addition to the online generated true random numbers, we will also generate pseudo random numbers for comparison. For this purpose, I have added tow additional functions to generate integer or decimals through the Delphi’s random function.

procedure TOnlineRandomizer.GetPseudoRandomDecimals(dPrecission,
dCount: Integer);
var
  I: Integer;
  rndDec:Single;
begin
  Randomize;
  for I := 1 to dCount do
  begin
    rndDec :=   Random;
    FResultList.Add(FloatToStr(rndDec,fSettings));
  end;
end;

procedure TOnlineRandomizer.GetPseudoRandomIntegers(iMin, iMax,
iCount: Integer);
var
  I,rndInt: Integer;
begin
  Randomize;
  for I := 1 to iCount do
  begin
    rndInt := Random(iMax-iMin+1)+iMin;
    FResultList.Add(intToStr(rndInt));
  end;
end;

Time For Test
Our randomizer class is ready, both for true and pseudo random number generations. Now, we need an application which we can get the random numbers through our class, analyze them with some statistical math and draw an error distribution graph to see the nature of random numbers. For this purpose I will use Delphi Firemonkey framework to collaborate all together.

One question here is about how we will analyze the random numbers. For this analyze, I will use the statistical grouping method. Assume that I have got 10 coins and throw them all. The most expected result is an equal distribution of Head and Tails, but it is not impossible to get extreme results like having all of them Heads or Tails. But the equal or close distribution of Head/Tails are more probable than the extreme results. For example; having all of them Head is equal to 1/ 210 probability and this means that I should start to hope seen this result after at least I throw the ten coin 1024 times. But more I throw, say a hundred thousand times, I should see all the possibilities distributed in the result set according to its probability. The exact figure of this result is normal curve which is stated as above. So what mathematical method should we use to get this graph?

We will throw the 10 coins as much as possible, or group the single tosses as to have 10 tosses in each. For each group we will count the heads and tails. If they are equal the error is 0, if heads are 1 more than the error is +1, if the tails are one more than the error is -1. This goes on. If all of them are heads the error is +5. So give an error point to each group, and regroup them according to their errors. Now you should count the number of groups for each error like How many of groups have +2 error. Plot the count of the groups for each error on the graph, so on th x-axis you will have 11 ticks, the middle one is for 0 error, left 5 ticks are for tail errors and right 5 ticks are for head errors. If this plot gives you a normal curve, t means that your numbers are true random numbers or pseudo numbers that have got a strong naturalness.

In the application that I called RandomNature, I used the above statistical method to analyze the random numbers. I have used 14 tosses for each group, but you can change this by just setting the errorStep variable in the Analyze function. After plotting the results on the graph, I fit them to a bezier curve using my own smoothing algorithm which I will describe in a future article. But it is in the code you can use it in any way.

According to the tests, I can say that the true numbers from Random.org works better than the machine generated ones especially in small amounts of tosses. Above is a result of both method, with a 10.000 total tosses.

The first result of a small set from Random.org. A 10.000 total tosses used.

The first result of a small set from Delphi’s Random function. A 10.000 of total tosses used.

As you can see from the graphs, the true numbers seem more natural, however when considering small sets, I have observed different results from these. Sometimes Delphi seemed more natural than the true numbers. This is because 715  tossing of 14 coins, doesnt give the natural results. It has an error potential of un-naturalness according to √n rule. So to be sure about the results we should make the error potential smaller using bigger amount of tosses. So lets look at the results of 100.000 coin tosses.

The result of 100.000 coin tosses from Random.org. It seems that Random.org numbers are really natural. To get a better normal curve results you should press the button more to get more random numbers.

The result of 100.000 coin tosses from Delphi’s Random function. It seems that Delphi’s randomness is not unnatural as it is expected . To get a better normal curve results you should press the button more to get more random numbers.

So as a result Delphi’s random function passed the test.

For downloading the full source code of the project with the OnlineRandomizer unit you can use this SVN link. For non-programmers the compiled Win32, Win64, MacOSX (Thanks to Firemonkey) applications are also available to download.


[1] Mark Kac, “What is random?”, American Scientist,v.71, pp.405

2 thoughts on “Understanding the nature of Randomness and Testing Delphi’s Random function

  1. Pingback: Testing The Random Number Generator In Delphi Firemonkey On Windows And OSX | Delphi XE5 XE6 XE7 Firemonkey, Delphi Android, Delphi IOS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s