• Status: Solved
• Priority: Medium
• Security: Public
• Views: 521

# Randomization function

I need a function work like Random... not Random exactly but work like it : generate a pseudo-random numbers which depend on a random seed ( It must be reliable dependancy on that random-seed ).

Of cource I need the source of that function.

Motaz from Sudan.
motaz1@yahoo.com
0
Motaz
• 7
• 5
• 5
• +7
1 Solution

Commented:
try this

function RandomNumber(Seed : Longint) : LongInt;
begin
randseed := seed;
Randomnumber := random(1000);
end;

do you mean this?

meikl
0

Author Commented:
No I don't want to use Random function at all, I want to make my own one.

Thanks
0

Commented:
Hi,
What kind of distribution do you want? Gaussian? Poisson?
Float? Integer? Slow? Fast? Accuracy?

I.e., what do you want it for?

/// John
0

Author Commented:
Integer and fast
0

Commented:
Hi,
I still want to know what you want it for, so it can be adapted.
Don't you want any distribution accuracy?

/// John
0

Commented:
When I wanted a fast random generator I used GetTickCount() and then mod it by some number to set the range.

This is not trully random, but was good enough provided called fairly infrequently
0

Commented:
Answers2000, that method is painfully slow, since you have to wait for the next tickcount before extracting a new pseudorandom number.

The GetTickCount function retrieves the number of milliseconds that have elapsed since the system was started. It is limited to the resolution of the system timer.

All ISA (IBM PC/AT and compatible) computer systems generate a hardware interrupt on IRQ0 18.2 Hz. This interrupt is mapped to INT 8 and can be intercepted by any application that wants to hook it. At 18.2 Hz, the interrupt occurs approximately once every 55 milliseconds. The Windows system driver hooks INT 8 and maintains the value returned by the GetTickCount function. Thus, this value is accurate only to within 55 milliseconds.

18.2 pseudorandom numbers/second isn't very fast, is it?
What "fast" means to me is >1MS/s.

/// John
0

Commented:
erajoj -

1. no offsense intended by your comment is plain wrong (re:speed of GetTickCount)

Try this program (C++ as I prefer that)

#include <windows.h>
#include <stdio.h>

int main( int argc, char *argv[] )
{
DWORD dwStart = GetTickCount() ;

for ( int x = 0 ; x < 100000 ; x++ )
{
DWORD dw = GetTickCount() ;
}

DWORD dwEnd = GetTickCount() ;

printf( "100000 retrieves of GetTickCount took %u milliseconds", (unsigned)(dwEnd-dwStart) ) ;

return 0;
}

On my system 100,000 retrieves of GetTickCount took 15 milliseconds.

GetTickCount returns (nearly) instantly.  It doesn't wait for another tick to occur.

015 seconds to 10^5 iterations

is  0.00000015 seconds per iteration

which is  0.00015 Milliseconds per iteration

2. no offsense intended by your comment is plain wrong (re:resolution).

This demonstrates it:

#include <windows.h>
#include <stdio.h>

int main( int argc, char *argv[] )
{
DWORD dwStart = GetTickCount() ;
DWORD dwX[100000] ;

for ( int x = 0 ; x < 100000 ; x++ )
{
dwX[x] = GetTickCount() ;
}

DWORD dwEnd = GetTickCount() ;

printf( "100000 retrieves of GetTickCount took %u milliseconds\n", (unsigned)(dwEnd-dwStart) ) ;

for ( int y = 0 ; y < 100 ; y++ )
{
printf( "%09u ", y, (unsigned)dwX[y] ) ;
}

printf( "\n" ) ;

return 0;
}

Output is

100000 retrieves of GetTickCount took 9 milliseconds
000000000 000000001 000000002 000000003 000000004 000000005 000000006 000000007
000000008 000000009 000000010 000000011 000000012 000000013 000000014 000000015
000000016 000000017 000000018 000000019 000000020 000000021 000000022 000000023
000000024 000000025 000000026 000000027 000000028 000000029 000000030 000000031
000000032 000000033 000000034 000000035 000000036 000000037 000000038 000000039
000000040 000000041 000000042 000000043 000000044 000000045 000000046 000000047
000000048 000000049 000000050 000000051 000000052 000000053 000000054 000000055
000000056 000000057 000000058 000000059 000000060 000000061 000000062 000000063
000000064 000000065 000000066 000000067 000000068 000000069 000000070 000000071
000000072 000000073 000000074 000000075 000000076 000000077 000000078 000000079
000000080 000000081 000000082 000000083 000000084 000000085 000000086 000000087
000000088 000000089 000000090 000000091 000000092 000000093 000000094 000000095
000000096 000000097 000000098 000000099
Press any key to continue

0

Commented:
eraroj -

A. Oops, sorry, typo in my program means you are right on #2 (but not #1)

printf( "%09u ", y, (unsigned)dwX[y] ) ;

should be

printf( "%09u ", (unsigned)dwX[y] ) ;

-- severe embarassment and red face

B. Having said that the Q'er didn't say he wanted fast.  A tick count is reasonable seed value for some other random number generator
0

Commented:
Hi,
No offence taken, since you don't seem to understand my comment.
"since you have to wait for the next tickcount" doesn't mean the function locks execution by that several subsequent values are equal.

And, could you tell me what "printf( "%09u ", y, (unsigned)dwX[y] ) ;" does?
Shouldn't it be "printf( "%04u %09u ", y, (unsigned)dwX[y] ) ;", or similar?

/// John
0

Commented:
hi, john!

it's always a pleasure to meet you.

Black Death.
0

Commented:
I wish it was mutual! ;-)))

/// John
0

Commented:

;-)))))))

Black Death.
0

Commented:
Well I got one for you ... it's in C ... converted from Fortran :) but it's good.  I was going to post it here but it's has alot of documentation makeing it longer than one of these comments should be...but go look at it they have lots of nice stuff there too.  If you need help converting the C to Delphi just ask.

http://www.neutralzone.org/home/faqsys/

http://www.neutralzone.org/home/faqsys/docs/random.c

0

Commented:
Hello all!

I convert the random generator from the C code on that page and here it is in Delphi... I didn't take much time to take a closer look so there might be some mistakes... Please someone who has got some free time and knows C try to see if I've made any mistakes in the code.. Thanks you.... Here is the code....
---------------------------------
var
u : array[0..97] of double;
c, cd, cm : double;
i97, j97 : integer;
test : boolean = FALSE;
procedure rmarin(ij,kl : integer);
var
i, j, k, l, ii, jj, m : integer;
s, t : double;
begin
if ((ij < 0) or (ij > 31328) or (kl < 0) or (kl > 30081)) then begin
ShowMessage('The first random number seed must have a value between 0 and 31328.');
ShowMessage('The second seed must have a value between 0 and 30081.');
exit;
end;
i := (ij div 177) mod 177 + 2;
j := ij mod 177 + 2;
k := (kl div 169) mod 178 + 1;
l := kl mod 169;
for ii := 0 to 97 do begin
s := 0.0;
t := 0.5;
for jj := 1 to 24 do begin
m := (((i*j) mod 179)*k) mod 179;
i := j;
j := k;
k := m;
l := (53*l + 1) mod 169;
if ((l*m) mod 64 >= 32) then
s := s + t;
t := t * 0.5;
end;
u[ii] := s;
end;
c := 362436.0 / 16777216.0;
cd := 7654321.0 / 16777216.0;
cm := 16777213.0 / 16777216.0;
i97 := 97;
j97 := 33;
test := TRUE;
end;

procedure ranmar(rvec : array of double; len : Integer);
var
ivec : integer;
uni : double;
begin
if (test = FALSE) then begin
ShowMessage('Call the init routine rmarin() before calling ranmar().');
exit;
end;
for ivec := 1 to len do begin
uni := u[i97] - u[j97];
if (uni < 0.0) then
uni := uni + 1.0;
u[i97] := uni;
Dec(i97);
if (i97=0)then
i97 := 97;
Dec(j97);
if (j97=0)then
j97 := 97;
c := c - cd;
if (c < 0.0)then
c := c + cm;
uni := uni - c;
if (uni<0.0)then
uni := uni + 1.0;
rvec[ivec] := uni;
end;
end;

{This is actually the main() function in C code...}

procedure TForm1.Button1Click(Sender: TObject);
var
temp : array[0..100] of double;
ij, kl, len, i : integer;
begin
ij := 1802;
kl := 9373;
rmarin(ij,kl);
len := 100;
for i := 0 to 200 do
ranmar(temp, len);
len := 6;
ranmar(temp,len);
for i := 1 to 6 do
ShowMessage(Format('%12.1f ',[4096.0*4096.0*temp[i]]));
end;
--------------------
Regards,
Viktor Ivanov
0

Commented:
eraroj -

>> And, could you tell me what "printf( "%09u ", y, (unsigned)dwX[y] ) ;" does?
>> Shouldn't it be "printf( "%04u %09u ", y, (unsigned)dwX[y] ) ;", or similar?

| As I said in previous comment
|
| printf( "%09u ", (unsigned)dwX[y] ) ;
|
|is what I meant
|
| -- this is to output array element y of array dwX as a 9 digit 0 preceded number

It's a mute point now, but I still think we were talking at cross purposes on the timer frequency issue (my point #1).  I won't hide my embarassment on my point #2 where I was plain wrong...

Anyway Greedy/Victor seem to have given an answer now.  So I'll leave this Q
0

Commented:
Why don't you want to use the Random? Is that because you need to generate numbers that will "represent" another distribution, rather then the Uniform[0,1]?
0

Author Commented:
I want to use a random for encryption, so that the important thing is random-seed.

If I get the code of Random function of pascal I'll be very thankful.

Motaz
0

Commented:
Hello MotaZ

There is the converted code of a C/C++ procedure for a random generator that Greedy pointed you to so you can give it a shot and see how it works,,,,

Regards,
Viktor Ivanov
0

Author Commented:
I test it but it didn't work.

I want a simple pascal code.

Motaz
0

Commented:
Hey, maybe someone more experienced could try to fix something I've missed??? Talk to you later.. Bye...

Regards,
Viktor Ivanov
0

Commented:
Hi Motaz,
Since you don't seem to need a good random function,
here is an equivalent of Borlands Random/Randomize functions...

unit Rand;

interface

var
RSeed: Integer = 0;

function  RandInt( Range: Integer ): Integer;
procedure RandomizeSeed;

implementation

const
kernel = 'kernel32.dll';

procedure GetSystemTime; external kernel name 'GetSystemTime';

function RandInt( Range: Integer ): Integer; register; assembler;
asm
IMUL EDX,RSeed,08088405H
INC  EDX
MOV  RSeed,EDX
MUL  EDX
MOV  EAX,EDX
end;

procedure RandomizeSeed; assembler;
var
systime : record
rgwDate : array [0..3] of Word;
wHour   : Word;
wMinute : Word;
wSecond : Word;
wMSec   : Word;
res     : array [0..7] of Char;
end;
asm
LEA     EAX,systime
PUSH    EAX
CALL    GetSystemTime
MOVZX   EAX,systime.wHour
IMUL    EAX,60
IMUL    EAX,60
XOR     EDX,EDX
MOV     DX,systime.wSecond
IMUL    EAX,1000
MOV     DX,systime.wMSec
MOV     RSeed,EAX
end;

end.

This will give you exactly the same results as Random(...)/Randomize.
If you need help with the assembler, just ask!

/// John
0

Commented:
Check out Robert Sedgewick's "Algorithms". Worth its weight in gold.
0

Author Commented:
Thanks very mush John.

Motaz
0

Commented:
Sorry for the late comment, but
if you want to see how the real function of Delphi work then take a look at I think System.pas and you'll see the code there...

Regards,
Viktor Ivanov
0

Commented:
Yes Viktor, and in what great effect is that code different from the one I provided? :-)
Not everybody has access to the Delphi source, you know (only Pro & C/S ).
I provided a slightly altered, although blatanty similar, version since it is a copyright violation in distributing parts of the Delphi source.

/// John
0

Commented:
Hello John!

I didn't see the source I just know it's there so I post a comment. I don't know if yours is same as the one provided by Inprise or not!

Regards,
Viktor Ivanov
0

Commented:
I notice you say you want to use this for encryption.

You should look up the swag of encryption components on DSP. They often come with source and will include cryptographically secure hashes (random number generators) such as MD5 or SHA1. These are much better to use than a ad hoc method for generating random numbers. You might even find it useful just to use one of these encryption components.

Hope This helps,

Raymond.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.