Watch, Follow, &
Connect with Us

Developer Tools Community.

Welcome, Guest
Guest Settings

Replies: 24 - Last Post: Aug 31, 2016 10:32 AM Last Post By: Andrej Mrvar
 Posts: 99 Registered: 10/20/10
 Random 64 bit Posted: Aug 3, 2016 2:19 AM It seems that random is not able to return int64 as a result? Am I right? How can I generate a random int64 number then (e.g. number in range 1..10,000,000,000)? Thanks. Andrej
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit Posted: Aug 3, 2016 2:22 AM   in response to: Andrej Mrvar Is trunc(10000000000 * random) + 1 precise enough? A.
 Posts: 125 Registered: 1/22/07
 Re: Random 64 bit Posted: Aug 3, 2016 2:34 AM   in response to: Andrej Mrvar Am 03.08.2016 um 11:22 schrieb Andrej Mrvar: Is 10000000000 * random precise enough? A. No... The base is still a longword Yo could do something like this (note there would be still a little problem - the numbers are up to 31 bits due to the fact that integer is used instead of longword): fucntion rand64(aRange : Int64) : int64; begin Result := ( int64(Random(MaxInt)) shl 32 ) or ( int64(Random(MaxInt)) ) mod aRange; end;
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit Posted: Aug 3, 2016 4:39 AM   in response to: Michael Rabatsc... Thanks. Probably mod should be executed at the end, therefore instead of Result := ( int64(Random(MaxInt)) shl 32 ) or ( int64(Random(MaxInt)) ) mod aRange; it should be Result := ( ( int64(Random(MaxInt)) shl 32 ) or ( int64(Random(MaxInt)) ) ) mod aRange; with additional ( and ) ?
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit Posted: Aug 3, 2016 5:45 AM   in response to: Andrej Mrvar Den 8/3/2016 kl. 13:39 skrev Andrej Mrvar: Thanks. Probably mod should be executed at the end, therefore instead of Result := ( int64(Random(MaxInt)) shl 32 ) or ( int64(Random(MaxInt)) ) mod aRange; it should be Result := ( ( int64(Random(MaxInt)) shl 32 ) or ( int64(Random(MaxInt)) ) ) mod aRange; with additional ( and ) ? https://sites.google.com/site/kbbsoft/delphi-progamming best regards Kim/C4D
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit Posted: Aug 3, 2016 6:54 AM   in response to: Kim Madsen Thanks for providing this list. That is a lot of work behind indeed. I am a bit lost with all this possibilities. Maybe you can suggest a simple random function to use to get integers in range 1 up to 10^10 (or 10^12 at most). Actually I do not need the whole range of 64 bit integers. Thanks in advance. A.
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit  Posted: Aug 3, 2016 9:09 AM   in response to: Andrej Mrvar Den 8/3/2016 kl. 15:54 skrev Andrej Mrvar: Thanks for providing this list. That is a lot of work behind indeed. I am a bit lost with all this possibilities. Maybe you can suggest a simple random function to use to get integers in range 1 up to 10^10 (or 10^12 at most). Actually I do not need the whole range of 64 bit integers. Thanks in advance. A. Whats your criteria for the random function? Consider: - Trueness? (ie.. is pseudo random good enough or must it rely on physical randomness?) - Speed? - Distribution of values? - Period? (how many random number generations before you start to see it starting over with the same list of "random" numbers) Its kind of a science to pick the best one for the job A simple pseudo random generator is the LCG. Its using last value generated to create next value. https://en.wikipedia.org/wiki/Linear_congruential_generator A function can easily be created for generating 64 bit psudo random LCG values like this: TRand64 = class private class var FValue:uint64; public class procedure Seed(const AValue:uint64); class function Rand:uint64; end; class procedure TRand64.Seed(const AValue:uint64); begin FValue:=AValue; end; class procedure TRand64.Rand:uint64; begin FValue:=(uint64(6364136223846793005)*FValue + uint64(1442695040888963407)) AND \$FFFFFFFFFFFFFFFF; Result:=FValue; end; Freely written. I havnt tried to compile it, but it ought to work best regards Kim/C4D
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit  Posted: Aug 3, 2016 9:24 AM   in response to: Kim Madsen Den 8/3/2016 kl. 18:09 skrev Kim Madsen: class procedure TRand64.Rand:uint64; begin ... Ofcourse that should be class function TRand64.Rand:uint64; begin ...
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 3, 2016 2:06 PM   in response to: Kim Madsen Thanks for providing the detailed solution. It works. But I wonder if the following solution is faster? Since I only need random numbers lower than 10^12 that is approx. 2^40, 40 bits=5 bytes, this 5 bytes should be sufficient: 8 bytes of the 64 bit integer result I fill in the following way: - the lower five bytes with random values, - the highest 3 bytes set to 0: Int64Rec(Result).Words[0] := Random(High(Word)); Int64Rec(Result).Words[1] := Random(High(Word)); Int64Rec(Result).Bytes[4] := Random(High(Byte)); Int64Rec(Result).Bytes[5] := 0; Int64Rec(Result).Words[3] := 0; Result:=Result mod (maxvalue); // maxvalue is for example 1000000000000 Is that ok?
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit  Posted: Aug 3, 2016 4:08 PM   in response to: Andrej Mrvar Den 8/3/2016 kl. 23:06 skrev Andrej Mrvar: Thanks for providing the detailed solution. It works. But I wonder if the following solution is faster? Since I only need random numbers lower than 10^12 that is approx. 2^40, 40 bits=5 bytes, this 5 bytes should be sufficient: 8 bytes of the 64 bit integer result I fill in the following way: - the lower five bytes with random values, - the highest 3 bytes set to 0: Int64Rec(Result).Words[0] := Random(High(Word)); Int64Rec(Result).Words[1] := Random(High(Word)); Int64Rec(Result).Bytes[4] := Random(High(Byte)); Int64Rec(Result).Bytes[5] := 0; Int64Rec(Result).Words[3] := 0; Result:=Result mod (maxvalue); // maxvalue is for example 1000000000000 Is that ok? Hi, It will provide you with some sort of randomness, but it wont be faster, and the period of that combination of random values is unknown. It may end up actually having a pretty bad randomness. Further it will be slower since Random is called multiple times, and internall Random makes something similar (although with different constants) to the one I provided. If you want a 40 bit random value, you can change it to: class function TRand64.Rand:uint64; begin FValue:=(uint64(6364136223846793005)*FValue + uint64(1442695040888963407)) MOD uint64(\$10000000000); Result:=FValue; end; best regards Kim/C4D
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 3, 2016 10:16 PM   in response to: Kim Madsen Thanks for explanation and the updated function for generating 40 bit random integer. I do not see how to use correctly? Should I first call TRand64.Seed with some number to initialize it (like randomize)? And later TRand64.Rand. Please provide me with an example of declarations needed and correct call of your function to obtain the random 40 bit integer.. Thanks. Andrej
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit  Posted: Aug 4, 2016 2:20 AM   in response to: Andrej Mrvar Den 8/4/2016 kl. 07:16 skrev Andrej Mrvar: Thanks for explanation and the updated function for generating 40 bit random integer. I do not see how to use correctly? Should I first call TRand64.Seed with some number to initialize it (like randomize)? And later TRand64.Rand. Please provide me with an example of declarations needed and correct call of your function to obtain the random 40 bit integer.. Thanks. Andrej Hi, Yes you ought to set Seed to something. There are two ways to use it: A) You set it to some fixed value (for example 0) everytime you want to have your "random" number sequence to start over from start. This obviously makes the random number non random, but instead predictable. Thats useful for creating test cases, where you want to be sure to compare a fixed outcome of some algorithm requiring random numbers. B) You can set it once in start of your application, to a value based on a time function. Like GetTickCount or similar changing value. This makes the "random" sequence unpredictable, which more resembles true randomness, and is what should typically be used when you run your application. After that you use the Rand function as many times as you need. best regards Kim/C4D The best n-tier for the best developers www.components4developers.com
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 4, 2016 3:22 AM   in response to: Kim Madsen Thanks, I see. A simple random number generator for generating integer numbers in range 1 to 10 billions would be also x := Random(1,000,000,000) + Random(10)*1,000,000,000 i.e. generating random number between 0 and one billion (standard random generator, since that is still 32 bit)) and than add zero, one, two, three ,..., or 9 billions by random. Am I right? Would that be random enough?
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit  Posted: Aug 4, 2016 5:22 AM   in response to: Andrej Mrvar Den 8/4/2016 kl. 12:22 skrev Andrej Mrvar: Thanks, I see. A simple random number generator for generating integer numbers in range 1 to 10 billions would be also x := Random(1,000,000,000) + Random(10)*1,000,000,000 i.e. generating random number between 0 and one billion (standard random generator, since that is still 32 bit)) and than add zero, one, two, three ,..., or 9 billions by random. Am I right? Would that be random enough? Hi, As I wrote, using Random multiple times potentially results in unknown periods and randomness. It may be good enough for your purpose, but only you know what you actually need. It will also be slower, but again, it may be fast enough for your purpose. Please check my previous replies on that topic. best regards Kim/C4D The best n-tier for the best developers http://www.components4developers.com
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 4, 2016 7:13 AM   in response to: Kim Madsen Thanks again for your answer. I can understand that your function is more random. One final question: would it be possible to rewrite your function in 'plain' pascal, I mean without defining new objects, classes, just function which returns int64 as a result? I just want to keep things as simple as possible
 Posts: 362 Registered: 12/13/99
Re: Random 64 bit 
Posted: Aug 4, 2016 9:14 AM   in response to: Andrej Mrvar
Den 8/4/2016 kl. 16:13 skrev Andrej Mrvar:
I can understand that your function is more random.

One final question:
would it be possible to rewrite your function in 'plain' pascal,
I mean without defining new objects, classes,
just function which returns int64 as a result?

I just want to keep things as simple as possible

Hi,

unit xxxx;

interface

procedure Seed(const AValue:uint64);
function Rand:uint64;

implementation

var FValue:uint64;

procedure Seed(const AValue:uint64);
begin
FValue:=AValue;
end;

function Rand:uint64;
begin
FValue:=(uint64(6364136223846793005)*FValue +
uint64(1442695040888963407)) MOD uint64(\$10000000000);
Result:=FValue;
end;

best regards
Kim/C4D
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 4, 2016 1:17 PM   in response to: Kim Madsen Thanks for your patience Now I included it to my program - the function is much simpler and according to testing also faster than other functions that I have tried before. And now a 'final final' two questions: For the starting value of FValue I take random 32 (actually 31) bit integer which is generated by Delphi itself: FValue:=uint64(random(maxint)); maybe: FValue:= uint64(random(maxint)) * uint64(random(maxint)) ); would be better? Since I finally need a int64 as a result, I divide the FValue by two, to avoid negative values: Result:= int64(FValue div 2) mod 10000000000; Do you agree with this or should I do it differently? Best. Andrej
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit   Posted: Aug 5, 2016 1:06 AM   in response to: Andrej Mrvar Hi, That should be fine. Although I personally would want to use Seed function to set the starting value (which can be anything as long as it fits in a 64 bit unsigned integer). This way you can reseed (when you need to), to a previous value and get the same "random" values again and again for testing purposes. When you run in production, you can seed it with random or gettickcount or trunc(now*10000)-trunc(now) or something like that. As long as the value is depending on "external circumstances" like a counter or a Real time clock or something with enough precision to make the seed start seem unpredictable. best regards Kim/C4D Den 8/5/2016 kl. 08:30 skrev Andrej Mrvar: Thanks for your patience Now I included it to my program - the function is much simpler and according to testing also faster than other functions that I have tried before. And now a 'final final' two questions: For the starting value of FValue I take random 32 (actually 31) bit integer which is generated by Delphi itself: FValue:=uint64(random(maxint)); maybe: FValue:= uint64(random(maxint)) * uint64(random(maxint)) ); would be better? Since I finally need a int64 as a result, I divide the FValue by two, to avoid negative values: Result:= int64(FValue div 2) mod 10000000000; Do you agree with this or should I do it differently? Best. Andrej
 Posts: 362 Registered: 12/13/99
 Re: Random 64 bit   Posted: Aug 5, 2016 1:09 AM   in response to: Kim Madsen BTW, you dont need to divide by 2 if you want the result in an int64. You asked for the function only to return 40 bits of the possible 64 bits, so you will be able to cast the value directly to int64 without problems. best regards Kim/C4D
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit   Posted: Aug 5, 2016 2:27 AM   in response to: Kim Madsen Thanks again. Problem solved now. No more questions Best wishes. Andrej
 Posts: 7,731 Registered: 9/22/99
 Re: Random 64 bit  Posted: Aug 9, 2016 12:39 AM   in response to: Andrej Mrvar Andrej Mrvar wrote: Is trunc(10000000000 * random) + 1 precise enough? A. No. Just generate two random Integers and do: MyRandomInt64 := Int64(RandomInt1) shl 32 or RandomInt2; -- Rudy Velthuis http://www.rvelthuis.de "This isn't life in the fast lane, it's life in the oncoming traffic." -- Terry Pratchett
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 10, 2016 1:30 AM   in response to: Rudy Velthuis (... No. Just generate two random Integers and do: MyRandomInt64 := Int64(RandomInt1) shl 32 or RandomInt2; As I learned there is at least one problem with this solution: Delphi random generator gives you random 31 bit number and not 32 bit number.
 Posts: 7,731 Registered: 9/22/99
 Re: Random 64 bit  Posted: Aug 10, 2016 3:02 AM   in response to: Andrej Mrvar Andrej Mrvar wrote: No. Just generate two random Integers and do: MyRandomInt64 := Int64(RandomInt1) shl 32 or RandomInt2; As I learned there is at least one problem with this solution: Delphi random generator gives you random 31 bit number and not 32 bit number. That's right. Simply do: RandomInt1 := RandSeed; Random(MaxInt); RandomInt2 := RandSeed; MyRandomInt64 := Int64(RandomInt1) shl 32 or RandomInt2; -- Rudy Velthuis http://www.rvelthuis.de "Every day people are straying away from the church and going back to God." -- Lenny Bruce
 Posts: 125 Registered: 1/22/07
 Re: Random 64 bit  Posted: Aug 29, 2016 3:21 AM   in response to: Andrej Mrvar Am 10.08.2016 um 10:30 schrieb Andrej Mrvar: No. Just generate two random Integers and do: MyRandomInt64 := Int64(RandomInt1) shl 32 or RandomInt2; As I learned there is at least one problem with this solution: Delphi random generator gives you random 31 bit number and not 32 bit number. Hey you can check out my random generator class from the mrMath library -> it got an implementation of the mersenne twister random generator. It results in an 32 bit value but it's "periodicity" is 2^19937 - 1 -> it also got an interface to the os random number functions as well as the Intel RDRAND assembler instruction. ( https://en.wikipedia.org/wiki/Mersenne_Twister) check it out on: https://github.com/mikerabat/mrmath kind regards Mike
 Posts: 99 Registered: 10/20/10
 Re: Random 64 bit  Posted: Aug 31, 2016 10:32 AM   in response to: Michael Rabatsc... Function provided by Kim Madsen worked just fine for me so I included it into my program. Thanks anyway. Andrej
Legend