Safely Generate Random Numbers Between Some Range in Java

Safely generate random numbers between some range in Java

The 'Math' library have Math.random() which generates a random value in [0, 1) range.

So don't use Math.random() - use this:

Random r = new Random();
int i = r.nextInt();

The docs for nextInt say:

nextInt() - Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. All 2^32 possible int values are produced with (approximately) equal probability.

It appears I misread the question slightly, and you need long not int - luckily the contract is the same.

long l = r.nextLong()

This will quite literally take two ints and jam them together to make a long.

Get random numbers in a specific range in java

Random rand = new Random(seed);
int random_integer = rand.nextInt(upperbound-lowerbound) + lowerbound;

How to generate random integers in a range

You could do

pepe = rng.nextInt(3) - 1;

rng.nextInt(3) returns a random element in the set {0, 1, 2} - therefore subtracting 1 returns a random element in the set {-1, 0, 1}, as desired.


Relevant documentation:

  • nextInt

Generate secure random number uniformly over a range in Java

You can do

Random rand = new SecureRandom()
// 0 to 100 inclusive.
int number = rand.nextInt(101);

or

// 0 inclusive to 100 exclusive.
int number = rand.nextInt(100);

Note: this is more efficient than say (int) (rand.nexDouble() * 100) as nextDouble() needs to create at least 53-bits of randomness whereas nextInt(100) creates less than 7 bits.

Generate two random numbers between 1 to 10 using specific string

Java has random number generator support via the java.util.Random class. This class 'works' by having a seed value, then giving you some random data based on this seed value, which then updates the seed value to something new.

This pragmatically means:

  • 2 instances of j.u.Random with the same seed value will produce the same sequence of values if you invoke the same sequence of calls on it to give you random data.
  • But, seed values are of type long - 64 bits worth of data.
  • Thus, to do what you want, you need to write an algorithm that turns any String into a long.
  • Given that long, you simply make an instance of j.u.Random with that long as seed, using the new Random(seedValue) constructor.

So that just leaves: How do I turn a string into a long?

Easy way

The simplest answer is to invoke hashCode() on them. But, note, hashcodes only have 32 bits of info (they are int, not long), so this doesn't cover all possible seed values. This is unlikely to matter unless you're doing this for crypto purposes. If you ARE, then you need to stop what you are doing and do a lot more research, because it is extremely easy to mess up and have working code that seems to test fine, but which is easy to hack. You don't want that. For starters, you'd want SecureRandom instead, but that's just the tip of the iceberg.

Harder way

Hashing algorithms exist that turn arbitrary data into fixed size hash representations. The hashCode algorithm of string [A] only makes 32-bits worth of hash, and [B] is not cryptographically secure: If you task me to make a string that hashes to a provided value I can trivially do so; a cryptographically secure hash has the property that I can't just cook you up a string that hashes to a desired value.

You can search the web for hashing strings or byte arrays (you can turn a string into one with str.getBytes(StandardCharsets.UTF_8)).

You can 'collapse' a byte array containing a hash into a long also quite easily - just take any 8 bytes in that hash and use them to construct a long. "Turn 8 bytes into a long" also has tons of tutorials if you search the web for it.

I assume the easy way is good enough for this exercise, however.

Thus:

String key = ...;
Random rnd = new Random(key.hashCode());

int number1 = rnd.nextInt(10) + 1;
int number2 = rnd.nextInt(10) + 1;

System.out.println("First number: " + number1);
System.out.println("Second number: " + number2);

How to generate a SecureRandom number with a specific bit range

First, a few comments:

  • The max value for 35 bits is 34359738367, not 68719476734.

    68719476734 is not even the max value for 36 bits, 68719476735 is.

  • Do not seed a SecureRandom. That reduces the security of it.

To generate a 35-bit random number, excluding value zero, just generate a long random value, take the last 35 bits, and redo if the value is zero.

SecureRandom r = new SecureRandom();

long value;
do {
value = r.nextLong() & ((1L << 35) - 1);
} while (value == 0);


Related Topics



Leave a reply



Submit