Random generates values between 0 and 1 for doubles ??? mystery... ???

1 view
Skip to first unread message

Skybuck Flying

unread,
May 14, 2015, 7:47:00 AM5/14/15
to
Hello,

I am a bit mystified about the "Random" routine in Delphi.

When I click "find declaration" in Delphi XE7... it will navigate to a
function which will look like:

function Random(const ARange: Integer): Integer;

So at first glance this function seems to return values between 0 and MaxInt
or so...

However Random is somehow capable of initializing doubles with values
between 0 and 1 ?

How can this be ??? Please clearify/solve this mystery for me ?!?

Example code:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

var
vIndex : integer;
vDouble : double;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
for vIndex := 0 to 1000 do
begin
vDouble := Random;
writeln( vDouble:16:16 );
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

Sample of output:

0.7212548679672182
0.2104894851800054
0.4930866835638881
0.6567967527080327
0.3219850626774132
0.5962043243926018
0.5341286454349756
0.4350875786039978
0.1325552123598754
0.5131898613180965
0.7825037101283669
0.7080669899005443
0.2223086454905570
0.4329185977112502
0.9693536832928658
0.7503404992166907
0.8087553470395505
0.4153525677975267
0.0065492829307914
0.9315644309390336
0.5416906108148396
0.4670365999918431
0.4646564479917288
0.5437774641904980

Bye,
Skybuck.

Skybuck Flying

unread,
May 14, 2015, 7:56:26 AM5/14/15
to
Apperently it's creating a bit of a problem for people porting code from
C/C++ to Delphi:

I think I just found a bug in Smart Sweeper from AIJunkie website:

The RandBool seems to produce always False.

When the integer version of Random is used it has to be +1 for example:

Random(2) will generate values between 0 and 1.

However

Random(1-0)+1

Ammounts to:
Random(1) which always returns 0, so this is definetly a bug in Smart
Sweeper's RandBool function...

I think this is another nice example how "inconsistent design" can lead to
problems ! ;)

Random behaves inconsistent for integers/whole numbers vs doubles/floating
points.

// Example program to demonstrate bug:

uses
System.SysUtils;

//returns a random integer between x and y
function RandInt(x, y: Integer): Integer;
begin
Result := Random(y - x) + x;
end;

//returns a random bool
function RandBool: Boolean;
begin
Result := RandInt(0, 1) = 1;
end;

var
vIndex : integer;
begin
try
for vIndex := 0 to 1000 do
begin
writeln( RandBool );
end;

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

Sample of output:

FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE

Bye,
Skybuck.

Skybuck Flying

unread,
May 14, 2015, 7:58:48 AM5/14/15
to
Here is a little fix for it:

// now I am going to fix it ! ;)
function RandBool: Boolean;
begin
Result := Random( 2 ) = 1;
end;

Bye,
Skybuck/

Skybuck Flying

unread,
May 14, 2015, 8:02:46 AM5/14/15
to
RandBool was/is never used in Smart Sweeper.

So in theory it is bugged, in practice it wasn't a problem.

Bye,
Skybuck.


Skybuck Flying

unread,
May 14, 2015, 11:39:12 AM5/14/15
to
My guess for now it's either:

1. "Compiler magic" ?

or

2. Perhaps function overloading, determined by function return type.

Bye,
Skybuck.

M Philbrook

unread,
May 14, 2015, 9:54:19 PM5/14/15
to
In article <3fcba$5554c1a0$5419aafe$17...@news.ziggo.nl>, skybuck2000
@hotmail.com says...
look at Randomize and Randseed

Jamie

Skybuck Flying

unread,
May 15, 2015, 12:01:36 AM5/15/15
to


"M Philbrook" wrote in message
news:MPG.2fbf1c537...@news.eternal-september.org...
Ok thanks Jamie.

Now that I look a bit further than my Nose long is I come across this:

function Random(const ARange: Integer): Integer;

...

function Random: Extended;

Indeed it seems like function overloading.

Conclusion:

"Find declaration" in this case sucks and is misleading/confusing !

It doesn't go to the correct location ?!

(I'll consider this a bug in the Delphi product ;) :))

(And a very nasty one !)

Bye,
Skybuck.

Skybuck Flying

unread,
May 20, 2015, 12:45:58 AM5/20/15
to
Mystery solved:

It's not function overloading, function overloading does not yet exist in
Delphi and perhaps for good reason too.

(Actually it does seem to exist somewhat... but then it all goes to
shit/hell... see below lol ***)

The real reason is: the integer version has a parameter and the
double/extended version does not.

(*** One last question which ghosts through my head is: what if the
parameter was optional ? hmmm)

( I explored this question and it's kinda funny a first in my Delphi
history:
[dcc32 Error] TestProgram.dpr(53): E2251 Ambiguous overloaded call to
'MyTest'
TestProgram.dpr(33): Related method: function MyTest: Double;
TestProgram.dpr(39): Related method: function MyTest(Integer): Integer;
)

I will post the secondary code to generate this error below the first
version.

// first version:
// *** Begin of Test Program ***

program TestProgram;

{

Test function overloading.

version 0.01 created on 20 may 2015 by Skybuck Flying

(Cause for this test is "Random" returning integer or double based on
variable which is assigned too.

Conclusion for now:

It does not seem to be function overloading which Random is using.

Thus my initial hunch that this might be compiler magic seems to be
warrented/have some merit.

Apperently the real reason for different versions of random is this:

the integer version is "parameterized", the double/extended version is not.

Which is kinda whacky but ok.

}


{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

function MyTest : double; overload;
begin
result := 666.666;
end;

{
function MyTest : integer; overload; // *** PROBLEM: identifier redeclared,
perhaps try in a unit ? ***
begin
result := 12345;
end;
}

procedure Main;
var
vInteger : integer;
vDouble : double;
begin
writeln('program started');

{
vInteger := MyTest;
writeln('vInteger: ', vInteger );
}
vDouble := MyTest;
writeln('vDouble: ', vDouble );

vInteger := Random( 5 );
writeln('vInteger: ', vInteger );

vDouble := Random;
writeln('vDouble: ', vDouble );

writeln('program finished');
end;


begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

// *** End of Test Program ***

// second version:
// *** Begin of Test Program ***

program TestProgram;

{

Test function overloading.

version 0.01 created on 20 may 2015 by Skybuck Flying

(Cause for this test is "Random" returning integer or double based on
variable which is assigned too.

Conclusion for now:

It does not seem to be function overloading which Random is using.

Thus my initial hunch that this might be compiler magic seems to be
warrented/have some merit.

Apperently the real reason for different versions of random is this:

the integer version is "parameterized", the double/extended version is not.

Which is kinda whacky but ok.

version 0.02 creates:

[dcc32 Error] TestProgram.dpr(53): E2251 Ambiguous overloaded call to
'MyTest'
TestProgram.dpr(33): Related method: function MyTest: Double;
TestProgram.dpr(39): Related method: function MyTest(Integer): Integer;

^^^ A first for me I think... kinda funny ^^^ =D

}


{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

function MyTest : double; overload;
begin
result := 666.666;
end;


function MyTest( Para : integer = 0 ) : integer; overload; // *** PROBLEM:
identifier redeclared, perhaps try in a unit ? ***
begin
result := 12345;
end;


procedure Main;
var
vInteger : integer;
vDouble : double;
begin
writeln('program started');


vInteger := MyTest;
writeln('vInteger: ', vInteger );

vDouble := MyTest;
writeln('vDouble: ', vDouble );

vInteger := Random( 5 );
writeln('vInteger: ', vInteger );

vDouble := Random;
writeln('vDouble: ', vDouble );

writeln('program finished');
end;


begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

// *** End of Test Program ***

Bye,
Skybuck.

Reply all
Reply to author
Forward
0 new messages