0

In the JDK doc of Random, they say "All 232 possible int values are produced with (approximately) equal probability". So I can generate any long number with approximately equal probability by generate the first 4 bytes with nextInt(), next 4 bytes with nextInt() then join them to create 8 bytes for a long.

Random r = new Random();
int firstPart = r.nextInt();
int secondPart = r.nextInt();
ByteBuffer bf = ByteBuffer.allocate(8);
bf.putInt(firstPart);
bf.putInt(secondPart);
long result = bf.getLong(0);

Is that true?

  • 4
    Leaving your question aside, `long result = (((long) firstPart)<<32) | secondPart` would probably work faster. – Federico klez Culloca Jun 21 '22 at 07:19
  • 5
    No this is not true. As stated on the docs for `nextLong`, calling `nextInt` twice in a row will not ensure all longs are possible since it is seeded by a 48bit value. As it stands, your implementation is approximately equivalent to that of `Random.nextLong` in function so you are better off using that. – Locke Jun 21 '22 at 07:21
  • 2
    Hm, it is indeed not entirely true, after all. – MC Emperor Jun 21 '22 at 07:30
  • @Locke so if I can call the `nextInt` second time from another `Random` that somehow is totally independent from the first `Random` then this could be achieved? – Trần Hoàn Jun 21 '22 at 07:50
  • @TrầnHoàn Yes, I thought about this as well. If you create two `Random` instances, you'll probably be fine. Note that many implementations of the argument-less `Random()` constructor uses `System.nanoTime()` to get the seed. – MC Emperor Jun 21 '22 at 08:01
  • 2
    [More info about seeds and 48 bits](https://stackoverflow.com/questions/22642918/why-does-random-nextlong-not-generate-all-possible-long-values-in-java) – MC Emperor Jun 21 '22 at 08:06
  • @TrầnHoàn Not really. Its just the same problem but a higher level of abstraction. In theory it is a little better, but the seeds are also produced in a predictable manor. If this is actually an issue then you should use `SecureRandom.nextLong()` instead to get a cryptographically secure result. – Locke Jun 21 '22 at 10:13
  • 3
    If being cryptographically secure is not required, just `ThreadLocalRandom.current().nextLong()` will give you a `long` where all values are possible with equal likelihood, with little overhead. – Holger Jun 21 '22 at 12:50
  • How many random longs do you need to generate? Do they all have to be distinct? How "random" do they need to be? – President James K. Polk Jun 21 '22 at 14:53
  • @Locke I know about SecureRandom, but this time it's not about cryptography. The main purpose of this question is to find a way that can quickly generate a long value, approximately equally distributed in the whole 2^64 values. And I use Random because I want to save the seeds to run the simulation again. – Trần Hoàn Jun 22 '22 at 01:48
  • 1
    `SplittableRandom` supports specifying the seed and has a 2⁶⁴ period. – Holger Jun 24 '22 at 15:54

0 Answers0