5

How can I create a random 64-bit integer value in Delphi 2006? The built-in integer-based Random() function seems to return only values between 0 and 2^31.

blerontin
  • 2,892
  • 5
  • 34
  • 60

6 Answers6

16

You can use my GpRandomGen. It implements Marsaglia/Zaman/James algorithm, is extremely fast and supposedly very random. Released as a freeware.

gabr
  • 26,580
  • 9
  • 75
  • 141
  • Seems like a full-featured random number generator although I would prefer a solution using native Delphi functions. The "this is the best known random number generator" statement on top of the file looks a bit too self-confident :-) – blerontin Dec 10 '10 at 13:11
  • Maybe it was the best in 2002. I have no idea what is the state of the art in random generation nowadays. – gabr Dec 10 '10 at 14:08
  • 4
    GpRandomGen `is` native Delphi. It does not rely on COM, .NET, ASM, etc. It contains references to the original published research articles, attribution to the original C implementat, etc. What more do you want? – Jeroen Wiert Pluimers Dec 10 '10 at 14:13
  • 2
    @blerontin I don't think there was any over-confidence. @gabr is not referring to his implementation as the best, rather he means that the algorithm (not due to him) was the best known RNG. That seems perfectly reasonable to me – David Heffernan Dec 10 '10 at 17:23
  • 4
    Actually that text ("best random generator") came with the algorithm. I merely copied the complete header while converting the source code. – gabr Dec 10 '10 at 18:10
  • Since google code is going away maybe it's time to update link to a new non-google-code source. – Warren P Dec 30 '15 at 21:25
10

Generate two 32 bit randoms and splice them together.

EDIT

Similar to @Andreas's answer I like the following (equivalent) implementation:

function Random64: UInt64;
var
  Overlay: packed record
    a, b: UInt32;
  end absolute Result;
begin
  Assert(SizeOf(Overlay)=SizeOf(Result));
  Overlay.a := Random32;
  Overlay.b := Random32;
end;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
5

To answer my own question I came up with the following code:

function GetRandomInt64() : int64;
begin
   Int64Rec(result).Words[0] := Random(High(Word));
   Int64Rec(result).Words[1] := Random(High(Word));
   Int64Rec(result).Words[2] := Random(High(Word));
   Int64Rec(result).Words[3] := Random(High(Word));
end;

Not sure if this is a valid solution or it will always create the same follow-up number X+1 after a given result number X.

blerontin
  • 2,892
  • 5
  • 34
  • 60
  • It depends on what you're using it for. This may be adequate for a simple source of randomness in a game or simulation. If it's for anything related to encryption, stay away from custom, ad-hoc solutions. Every programmer eventually comes up with the idea of combining random sources to create large random numbers. It's a very bad idea in general. – Ferruccio Dec 10 '10 at 13:20
  • It's for creating unique file names. Needs not to be encryption-safe. – blerontin Dec 10 '10 at 13:30
  • @Ferruccio: Out of interest, what's wrong with blerontins suggestion? How can it be exploited? If I needed a 64-bit random number, and only had a 32-bit generator, I would probably just concatenate and believe it was safe. Why isn't it? – Svein Bringsli Dec 10 '10 at 13:49
  • 4
    You're doing this for file names? Why do you need 64-bit numbers for that? Are you really creating more than 2 billion files? – Rob Kennedy Dec 10 '10 at 14:33
  • 9
    @blerontin Why don't you use the Windows API to get temporary file names? – David Heffernan Dec 10 '10 at 14:52
  • @Svein. I don't know how it can be exploited. That's the problem. Like most engineers, I'm not qualified to do that sort of cryptographic analysis. It's probably fine for generating unique file names as long as you have a way to deal with collisions. I suspect that taking the high bits from four random numbers and combining them will tend to decrease the periodicity of your rng. – Ferruccio Dec 10 '10 at 16:25
  • 2 Ferruccio, Svein Bringsli: it is not even random, but merely 4 adjacent values from `Random(High(Word))` sequence packed together. Linear congruent generator is deterministic! Also, never returns `FFFF FFFF FFFF FFFF` – Free Consulting Dec 10 '10 at 18:50
  • If using if for a filename why not use a guid as a base? – Remko Dec 10 '10 at 19:07
  • @David: +1 (isn't there a shell api that returns a unique filename?) – Remko Dec 10 '10 at 19:10
  • 4
    @Remko Indeed there is, it's called GetTempFileName: http://msdn.microsoft.com/en-us/library/aa364991%28VS.85%29.aspx and in my view it is the canonical solution to this problem – David Heffernan Dec 10 '10 at 19:26
  • @David: Just wanted you to mention it :D – Remko Dec 10 '10 at 21:28
4

You can generate 64 random bits and interpret the result as an integer. (63 bits if you are working with signed integers and want the result to be non-negative.) Equivalently you can take two random integers in the range 0..2^31-1, plus two extra random bits, and concatenate them to get a random 64-bit integer.

EDIT: I was curious about the statistical properties of pseudo-random numbers generated by concatenating pseudo-random components and found that (apparently) this approach might not work well depending on your pseudo-random generator (of course for true random number generation, as from atmospheric noise, concatenating random bits is no problem). For recreational use, the loss of various statistical properties might be acceptable, but for more serious use you might end up needing a custom pseudo-random generator as @gabr suggested. Here is a related question: Best method of generating a number with 256 random bits?

Community
  • 1
  • 1
Mitch Schwartz
  • 1,503
  • 9
  • 9
4

Create a GUID (eg CoCreateGuid) and cast it to Int64.

Remko
  • 7,214
  • 2
  • 32
  • 52
3

Simple:

function Random64: UInt64;
begin
  PCardinal(@result)^ := Random32;
  PCardinal(cardinal(@result) + 4)^ := Random32;
end;

where Random32 is your favourite 32-bit unsigned integer random number function.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384