Create random BigInteger using RandomGenerator (introduced in Java 17) - java

The class BigInteger provides the constructor
public BigInteger(int numBits, Random rnd)
Since Java 17 the use of RandomGenerator is encouraged. How can I generate a random BigInteger in the range 0...(2^n)-1 using only an instance of RandomGenerator.

Just using Random & SecureRandom
Why do you need this? Because the new Random() gets you a relatively fast non-secure random number generator and new SecureRandom() provides a CSPRNG (Cryptographically Secure Pseudo Random Number Generator). Both those instances are instances of the RandomGenerator interface. So the only time you'd need this is if you want a specific Random generator defined in the random package.
If you don't need speed and you haven't any specific needs regarding the distribution - you'd probably know if you'd have any - then please just use new BigInteger(n, new SecureRandom()).
Implementing Random
TL;DR: don't
As RandomGenerator is an interface. The Random class has been refactored into a class that implements the interface. That means you can use the old Random wherever an interface specifies RandomGenerator. However, that doesn't work the other way around.
Random itself is not a final class, so it can be inherited from. So you could, in principle, create an adapter class by simply implementing all methods in Random and calling the similarly named methods of a wrapped RandomGenerator. This is however very dangerous practice as future extensions of Random may break everything. In the worst case it will show inconsistent behavior by mixing the state of the parent Random object and the wrapped RandomGenerator.
Move to Java 19
In Java 19 (build b21) there is an adapter method provided for RandomGenerator named Random#from(RandomGenerator). You can see the feature request here. Note that this is an intermediate step; preferably the BigInteger method should be retrofitted to use RandomGenerator (as stated in the feature request).
Beware that you should never use this wrapper class if you suspect that setSeed can ever be called, e.g. when generating a large prime in the BigInteger class. If it is called it will generate an UnsupportedOperationException.
These kind of classes go through all kinds of testing so the Java provided method can be trusted. However, the fact that a method can be retrofitted to use setSeed could be a problem regarding forward compatibility - you have been warned.
The special case of [0, n^2)
However, you've got one out: the range 0..2^n-1 or [0, 2^n-1) is a number consisting of a set of bits. So what you can do is use your RandomGenerator, fill an array of bytes, remove the most significant bits from the first byte (as Java is big endian), and then convert the array into a signed integer:
/**
* Mimics the {#link BigInteger#BigInteger(int, Random)} function using a
* {#link RandomGenerator} instance.
*
* #param numBits maximum bitLength of the new BigInteger.
* #param rnd source of randomness to be used in computing the new
* BigInteger.
* #throws IllegalArgumentException {#code numBits} is negative.
* #see #bitLength()
*/
public static BigInteger generateRandomBigInteger(int numBits, RandomGenerator rng) {
if (numBits < 0) {
throw new IllegalArgumentException("numBits must be non-negative");
}
if (numBits == 0) {
return BigInteger.ZERO;
}
int bytes = (numBits + Byte.SIZE - 1) / Byte.SIZE;
// mask bits that we need the value of to 1, the others - if any -- will be set
// to zero
byte bitMask = (byte) ((1 << ((numBits - 1) % Byte.SIZE + 1)) - 1);
byte[] randomBytes = new byte[bytes];
rng.nextBytes(randomBytes);
randomBytes[0] &= bitMask;
return new BigInteger(1, randomBytes);
}
numBits is of course the same as your n variable.
The case for [0, max)
Actually, you can combine the comparison function and the random bit generator in such a way that you can create large random values in the range 0..max with max having any value, with a minimum amount of random bits and no nasty BigInteger operations (such as division) at all.
You can find my implementation of that here but you may get weirded out. Sorry in advance, and yes, this is a shameless plug of my RNGBC algorithm :)

Related

UUID.randomUUID() vs SecureRandom

I am trying to understand the advantages of using UUID.randomUUID() over SecureRandom generator as the former uses securerandom internally.
Well, the source code shows UUID.randomUUID uses SecureRandom.
public static UUID [More ...] randomUUID() {
SecureRandom ng = numberGenerator;
if (ng == null) {
numberGenerator = ng = new SecureRandom();
}
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
As you can see, you can use either, but in a secure UUID you have 6 non-random bits, which can be considered a disadvantage if you are picky.
Random numbers have a random chance of being repeated. The lower the randomness (unless there is some co-ordination), the greater the chance of producing the same number twice.
https://en.wikipedia.org/wiki/Birthday_problem
As you produce more random numbers the chance of the same number being repeated increases as every id must be different to every other id.
SecureRandom allows you to choose how many bit of randomness you want. Make it too small and there is a good chance they will be repeated. You can get duplicate random 32-bit id in a fraction of a second.
UUID sets the standard at 128 bits (or as uoyilmaz points out, 122 bits are random) This is enough for most use cases. However if you want a random String, I would be tempted to use more bits and/or a higher base than 16. Java for example support base 36 and 64 which means you can have shorter ids, or more randomness for the same length ID.
Note: UUID format has multiple - in it's dump though I don't see the value of them, they just make the string longer.
Thanks for all the provided technical answers. I, myself, was also baffled by the difference between the two which led me here. But then, a thought dawned on me: If you only call the function once, then there is no difference as both method generates a number that could not be pre-calculated. But if call the function several times, then they differ here because a statistical normal distribution is a property of a random number generator whereas this is not a property of a UUID. UUID strives for uniqueness and in fact it derives the provided number using your computer's MAC hardware address, the current epoch seconds etc. And eventually, if you for-loop call the UUID values it will not be statistically normally distributed.
The UUID is not a random number: it is a universal unique ID. You can be sure that no one can generate the same hexadecimal string.
A random number is another story: it is not an hexadecimal string and it is not universally unique.
A more efficient and completed generator of UUIDs is provided by this library.

What is random seed about?

For example the code below. It has a random class. However it always produce the same output everywhere . In this case which item is the seed?
source: link
import java.util.Random;
public class RandomTest {
public static void main(String[] s) {
Random rnd1 = new Random(42);
Random rnd2 = new Random(42);
System.out.println(rnd1.nextInt(100)+" - "+rnd2.nextInt(100));
System.out.println(rnd1.nextInt()+" - "+rnd2.nextInt());
System.out.println(rnd1.nextDouble()+" - "+rnd2.nextDouble());
System.out.println(rnd1.nextLong()+" - "+rnd2.nextLong());
}
}
42 is the seed, as the very same Javadoc says. So, what is a seed? A random number is seldom truly random - often it's a pseudo-random instead. This means it's generated from a function, which is said PRNG (pseudo random number genrator). Being generated from a function, in turn, means that the output is not random anymore, since it's predictable!
However, depending on your needs, this pseudo-randomness may be enough - I said enough because generating random bit is expensive, and I'm not talking about time or memory, but about money (see this link on wikipedia). So, for example, if you need a random value to place enemies in your game, a pseudo-random number is ok - but if your are building security-related software, you want to use a true random number, or at least a cryptographically secure PRNG.
How can we describe a PRNG, like the one used in Math.random()? It's a function, initialized with a seed S that returns an array of values A. Note that, for each integer S, is defined one and only one array A. For example (values are not actual):
first call second call third call
seed: 14329 .18 .82 .5
seed: 3989 .7 .02 .93
So you seed you PRNG with some known value when you want its result to be predictable - for example for testing purposes or to ensure that, each time you run level 1 in your game, the enemies are always placed in the same (pseudo) random places - otherwise you don't need to explicitely pass a seed.
Random Seed on Wikipedia:
A random seed (or seed state, or just seed) is a number (or vector)
used to initialize a pseudorandom number generator.
In other word, it is the number from which a seem-to-be-random sequence will be generated. Therefore, if you use the same number, the senquence will always be the same.
In practice, we usually use System Time as seed.
The seed is given as the argument of the constructor of Random; using the same seed will yield the same sequence of numbers. However this is discussed under the link in thet question.
In this case the seed is 42. This is the reason for the same output - you use the same seed.
You can use for example
Random rnd1 = new Random(System.currentTimeMillis())
for different outputs.
The seed is the initial value of the internal state of the pseudorandom number generator which is maintained by method next(int).
The invocation new Random(seed) is equivalent to:
Random rnd = new Random();
rnd.setSeed(seed);
From the Java documentation in the Random class
Creates a new random number generator using a single long seed. The seed is the initial value of the internal state of the pseudorandom number generator which is maintained by method next(int).
The invocation new Random(seed) is equivalent to:
Random rnd = new Random();
rnd.setSeed(seed);
So 42 is the seed given to the new Random() in your example

math.random() follows which algorithms

Am using math.random() method to generate random numbers. but i had a doubt about that method. math.random() is which algorithms will fallow to generate random numbers. Is there any another random number generated algorithm?
Am trying this code but i think this is not efficient to generate random code:
for (int i = 0; i < N; i++) {
int sd = i + (int) (Math.random() * (N-i));
String t = one[r];
one[r] = one[i];
one[i] = t;
}
Is there any better algorithm for random number generation?
Java mainly provides four random number generator API's depending of your use case.
java.lang.Math.random()
If we check the Math class source code, we can view this:
private static Random randomNumberGenerator;
private static synchronized void initRNG() {
if (randomNumberGenerator == null)
randomNumberGenerator = new Random();
}
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
Math.random() is simply a shortcut to call Random Class. It is more simple and less complete than java.util.Random but it's enough in some cases.
java.util.Random
The Random class implement a Linear Congruential Generator.
LCG is a pretty simple formula for Pseudorandom Number Generation. java.util.Random is not trully random, it is totally deterministric. With the same initial condition (also called the seed), you've got the same result in the same order.
Use java.util.Random is good for the most use cases (simulation, games, ...) but is not good for cryptography because of his predictability, for this kind of use case prefer java.security.SecureRandom.
java.util.Random is thread safe but can have performance issues in multi-threaded context. If you work in a multi-threaded application, prefer ThreadLocalRandom.
java.security.SecureRandom
The SecureRandom class extend java.util.Random class to implement a cryptographically strong random number generator based on an entropy source. SecureRandom is not deterministic.
SecureRandom have multiple implementation in function of your platform (the complete implementation list).
java.security.SecureRandom is less fast than java.util.Random because of entropy source.
java.util.concurrent.ThreadLocalRandom
The ThreadLocalRandom class is another implementation of Linear Congruential Generator but this one isn't thread-safe but dedicated to a specific thread.
This implementation is more fast than java.util.Random in multi-threaded context.
In your case, you could use java.util.Collections.shuffle(list) to shuffle your array with java.util.Random or with a specific Random Generator like java.security.SecureRandom.
Use java.util.Random API
An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed, which is modified using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.)
Algorithm class : pseudorandom number generator known as PRNG. You can read more about it here.
Note : Math.random() also uses java.util.Random instance to generate the psuedo-random numbers internally
It uses the pseudo random number generation algorithms ie the numbers which are constantly fluctuating from throughout the system.
You may also find this interseting to read:- Pseudo-Random vs. True Random
Also check the Source for java.util.Random
The simplest way to do what you are trying to do is
String[] words = ...
Collections.shuffle(Arrays.asList(words));
You are right that generating a random double and then turning it into a small integer is not efficient. Fortunately Random has a method for this.
Random rand = new Random();
for (int i = words.length - 1; i > 0; i--) {
int sd = rand.nextInt(i+1); // random number between 0 and i inclusive
String t = words[r];
words[r] = words[i];
words[i] = t;
}
Here are 2 methods to Shuffle an Array:
Approach 1: Shuffle elements in an array
Approach 2: Java Collection.shuffle() method
And the method you use is one standard way accomplishing this.
There are 2 ways in java: java.util.Random and java.lang.Math.random.
java.lang.Math.random() uses java.util.Random.
It provides only doubles and has no seeding capability.

generating Random integers in a range(code) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java: generating random number in a range
I am unable to understand what is happenning in class Random and in it's methods.
will someone explain it,plz?
or is there any simpler way also to generate random numbers?
Note:I want to understand the code of the function (Random.nextInt),not how to use it.
If you want random integers between x (inclusive) and y (exclusive), here's what you do:
int yourRandomNumber = new Random().nextInt(y-x) + x;
Example: if you want a random selection of [4,5,6,7], you will do:
int yourRandomNumber = new Random().nextInt(4 /* i.e. 8-4 */) + 4;
What is difficult to understand? There are methods for generating nearly every type of random number... The one you want is probably this:
int nextInt(int n)
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
EDIT: You ask how the function actually works. This too is explained in the javadoc of the function. If you're more interested in details, you should probably get the D. Knuth book referenced in the docs (from http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html):
An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed, which is modified using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume 2, Section 3.2.1.)
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class Random. Java implementations must use all the algorithms shown here for the class Random, for the sake of absolute portability of Java code. However, subclasses of class Random are permitted to use other algorithms, so long as they adhere to the general contracts for all the methods.
The algorithms implemented by class Random use a protected utility method that on each invocation can supply up to 32 pseudorandomly generated bits.
Many applications will find the random method in class Math simpler to use.

Java random always returns the same number when I set the seed?

I require help with a random number generator I am creating. My code is as follows (inside a class called numbers):
public int random(int i){
Random randnum = new Random();
randnum.setSeed(123456789);
return randnum.nextInt(i);
}
When I call this method from another class (in order to generate a random number), it always returns the same number. For example if I were to do:
System.out.println(numbers.random(10));
System.out.print(numbers.random(10));
it always prints the same number e.g. 5 5. What do I have to do so that it prints two different numbers e.g. 5 8
It is mandatory that I set the seed.
Thanks
You need to share the Random() instance across the whole class:
public class Numbers {
Random randnum;
public Numbers() {
randnum = new Random();
randnum.setSeed(123456789);
}
public int random(int i){
return randnum.nextInt(i);
}
}
If you always set the seed, you will always get the same answer. That is what setting the seed does.
There are two issues causing what you see. The first is that the code sets a seed value for a Random instance. The second is that the instance method "random" instances a new Random object and then immediately sets its seed with the same seed every time. The combination of these two guarantees that, for the same value of i, the method "random" will always return the same value and it will always be the first in the sequence that the seed always generates.
Assuming setting the seed is mandatory, to get the next value in the sequence instead of the same first value of the sequence every time, the randnum instance of Random can't have its seed set every time just before its next method gets called. To fix that, move the randnum local variable instance of Random from the scope of the random instance method to the class scope. Second, set the seed only when random is assigned a Random instance or only to get same sequence of results from it to start over again. Class Random's setSeed(long seed) instance method can't execute in the class scope, so the constructor has to set it using the Random constructor with the long seed parameter. The following code shows the changes:
public class RandomDemo { // arbitrary example class name
// lots of class related stuff may be here...
// still inside the class scope...
// private is a good idea unless an external method needs to change it
private Random randnum = new Random(123456789L);
// the seed guarantees it will always produce the same sequence
// of pseudo-random values when the next methods get called
// for unpredicable sequences, use the following constructor instead:
// private Random randnum = new Random();
// lots of code may be here...
// publicly exposed instance method for getting random number
// from a sequence determined by seed 123456789L
// in the range from 0 through i-1
public int randnum(int i) {
// don't set the seed in here, or randnum will return the exact same integer
// for the same value of i on every method call
// nextInt(i) will give the next value from randnum conforming to range i
return randnum.nextInt(i);
} // end randnum
// lots of more code may be here...
} // end class RandDemo
The above will give you an exact solution to your exact problem, as stated. However, using a mandatory seed seems unusual, given what it does.
If this is for a class project or software testing where the sequence has to be predictable and repeatable, setting the seed to a fixed value makes sense. Otherwise, question the validity of setting the seed to some predetermined value. The following explains more about Random, seeds for Random and why there is a provision for supplying a seed.
Random has two constructors:
Random()
and
Random(long seed)
and an instance method
setSeed(long seed)
that all affect the sequence of numbers obtained from a Random instance. The instance method,
setSeed(long seed)
sets the Random object to the same state it would have been in had it been just instanced with the same seed as the constructor argument. Only the low-order 48 bits of a seed value get used.
If a Random object is instanced without a seed, the seed will be the same as the system time in milliseconds. This ensures that, unless two Random objects are instanced in the same millisecond, they will produce different pseudo-random sequences. Only the low order 48 bits of the seed value gets used. This causes unpredictable pseudo-random sequences. It is not necessary and wasteful of computing resources to get a new instance of Random every time one calls a next method.
Random's seed parameters are provided so that one may instance a Random object that produces a sequence that is repeatable. For a given seed, the sequence of values in next methods are guaranteed to be the same sequence whenever that seed is used. This is useful for testing software that is going to use pseudo-random sequences where results have to be predicable and repeatable. It is not useful for creating different unpredictable pseudo-random sequences in operation.
The statement "it is mandatory that I set the seed" negates any unpredictablity of the Random object's pseudo-random sequences. Is this for a class project or software test where results have to be the same for the same inputs to the program?
Set the seed once on startup, rather than every time you want a new random number.
What you are using is not a Random Number Generator, it's a Pseudo-Random Number Generator. PRNG's generate sequences of pseudo-random numbers, the seed selects a starting point in a sequence (a PRNG may generate one or several sequences).
Do you necessarily need to create the new Random() inside your random(int i) method? If you are OBLIGED to do it that way, you could use, you could set the seed to the current time, although that is not fail proof, because you could call your numbers.random(10) so fast after the other that it would end up being the same seed. You could try maybe using nanoSeconds (System.nanoTime() I think? And if setSeed only accepts int, multiply it I guess).
What I would suggest however, if you are allowed to do so, is to declare your Random outside your method. If you instanciate your random variable in, say, your number class constructor, you could set any seed and any time you call your method it would give you a new number. (They will be the same sets of numbers every time you restart your application if you use a constant seed however, you could use time as your seed in this case too).
Finally, the last problem could be if you declare several number classes at the same time. They will all have the same random seed and give you the same set of random numbers. If this happens, you can make a static Random in your main class, and call it in your numbers class. This will couple those two classes though, but it would work. Another option would be to send an incrementing value to your number class constructor, for each number you instanciate, and use the value you pass as the seed.
The second option should be good for you though, if you are allowed to do it that way.
Usually, Random is not truly random but pseudorandom. It means it takes a given seed and uses it to generate a sequence of numbers that looks like random (but is enterely predictable and it repeats if you put the same seed).
If you don't put seed, then the first seed will be taken from a variable source (usually the system time).
Usually, a value with seed will be used in order to have it repeat the exact values (for example, for testing). Use Random without seed instead.

Categories