Here the code for a Simple random generator:
public class SimpleRandom {
/**
* Test code
*/
public static void main(String[] args) {
SimpleRandom rand = new SimpleRandom(10);
for (int i = 0; i < 25; i++) {
System.out.println(rand.nextInt());
}
}
private int max;
private int last;
// constructor that takes the max int
public SimpleRandom(int max){
this.max = max;
last = (int) (System.currentTimeMillis() % max);
}
// Note that the result can not be bigger then 32749
public int nextInt(){
last = (last * 32719 + 3) % 32749;
return last % max;
}
}
The code above is a "Linear congruential generator (LCG)", you can find a good description of how it works here.
Disclamer:
Answer from Frank on Stack OverflowThe code above is designed to be used for research only, and not as a replacement to the stock Random or SecureRandom.
Do you guys use Math.random() or the Random class more often for generating random numbers?
java - Math.random() versus Random.nextInt(int) - Stack Overflow
how random is Math.random() in java across different jvms or different machines - Stack Overflow
How do I generate random integers within a specific range in Java? - Stack Overflow
Videos
Here the code for a Simple random generator:
public class SimpleRandom {
/**
* Test code
*/
public static void main(String[] args) {
SimpleRandom rand = new SimpleRandom(10);
for (int i = 0; i < 25; i++) {
System.out.println(rand.nextInt());
}
}
private int max;
private int last;
// constructor that takes the max int
public SimpleRandom(int max){
this.max = max;
last = (int) (System.currentTimeMillis() % max);
}
// Note that the result can not be bigger then 32749
public int nextInt(){
last = (last * 32719 + 3) % 32749;
return last % max;
}
}
The code above is a "Linear congruential generator (LCG)", you can find a good description of how it works here.
Disclamer:
The code above is designed to be used for research only, and not as a replacement to the stock Random or SecureRandom.
In JavaScript using the Middle-square method.
var _seed = 1234;
function middleSquare(seed){
_seed = (seed)?seed:_seed;
var sq = (_seed * _seed) + '';
_seed = parseInt(sq.substring(0,4));
return parseFloat('0.' + _seed);
}
Here is the detailed explanation of why "Random.nextInt(n) is both more efficient and less biased than Math.random() * n" from the Sun forums post that Gili linked to:
Math.random() uses Random.nextDouble() internally.
Random.nextDouble() uses Random.next() twice to generate a double that has approximately uniformly distributed bits in its mantissa, so it is uniformly distributed in the range 0 to 1-(2^-53).
Random.nextInt(n) uses Random.next() less than twice on average- it uses it once, and if the value obtained is above the highest multiple of n below MAX_INT it tries again, otherwise is returns the value modulo n (this prevents the values above the highest multiple of n below MAX_INT skewing the distribution), so returning a value which is uniformly distributed in the range 0 to n-1.
Prior to scaling by 6, the output of Math.random() is one of 2^53 possible values drawn from a uniform distribution.
Scaling by 6 doesn't alter the number of possible values, and casting to an int then forces these values into one of six 'buckets' (0, 1, 2, 3, 4, 5), each bucket corresponding to ranges encompassing either 1501199875790165 or 1501199875790166 of the possible values (as 6 is not a disvisor of 2^53). This means that for a sufficient number of dice rolls (or a die with a sufficiently large number of sides), the die will show itself to be biased towards the larger buckets.
You will be waiting a very long time rolling dice for this effect to show up.
Math.random() also requires about twice the processing and is subject to synchronization.
another important point is that Random.nextInt(n) is repeatable since you can create two Random object with the same seed. This is not possible with Math.random().
Math.random() is based on java.util.Random, which is based on a linear congruential generator. That means its randomness is not perfect, but good enough for most tasks, and it sounds like it should be sufficient for your task.
However, it sounds like you're using the double return value of Math.random() to choose between a fixed number of choices, which may further degrade the quality of the randomness. It would be better to use java.util.Random.nextInt() - just be sure to reuse the same Random object.
Sometimes, it doesn't appear so random by looking at a snapshot on a resource pool to see which pieces it's getting at that instant
Our brains are really good at spotting patterns in perfect randomness, so that means almost nothing.
Math.Random's algorithm is "random enough" for any platform. The mathematical model used for creating psuedo-random numbers is a good one. It depends on how many threads you use. For anything but a really large number of threads, this will not give you even distribution (the nature of random numbers), and then Math.random() will give you plenty of overhead.
Try a better option: make a resource pool class, which distributes them evenly - and then just keep it's critical section in the "distribute" method protected.
Java 7+
In Java 1.7 or later, the standard way to do this (generate a basic non-cryptographically secure random integer in the range [min, max]) is as follows:
import java.util.concurrent.ThreadLocalRandom;
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);
See the relevant JavaDoc. This approach has the advantage of not needing to explicitly initialize a java.util.Random instance, which can be a source of confusion and error if used inappropriately.
However, conversely with ThreadLocalRandom there is no way to explicitly set the seed so it can be difficult to reproduce results in situations where that is useful such as testing or saving game states or similar.
Java 17+
As of Java 17, the psuedorandom number generating classes in the standard library implement the RandomGenerator interface. See the linked JavaDoc for more information. For example, if a cryptographically strong random number generator is desired, the SecureRandom class can be used.
Earlier Java
Before Java 1.7, the standard way to do this is as follows:
import java.util.Random;
/**
* Returns a pseudo-random number between min and max, inclusive.
* The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* @param min Minimum value
* @param max Maximum value. Must be greater than min.
* @return Integer between min and max, inclusive.
* @see java.util.Random#nextInt(int)
*/
public static int randInt(int min, int max) {
// NOTE: This will (intentionally) not run as written so that folks
// copy-pasting have to think about how to initialize their
// Random instance. Initialization of the Random instance is outside
// the main scope of the question, but some decent options are to have
// a field that is initialized once and then re-used as needed or to
// use ThreadLocalRandom (if using at least Java 1.7).
//
// In particular, do NOT do 'Random rand = new Random()' here or you
// will get not very good / not very random results.
Random rand;
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
See the relevant JavaDoc. In practice, the java.util.Random class is often preferable to java.lang.Math.random().
In particular, there is no need to reinvent the random integer generation wheel when there is a straightforward API within the standard library to accomplish the task.
Note that this approach is more biased and less efficient than a nextInt approach, https://stackoverflow.com/a/738651/360211
One standard pattern for accomplishing this is:
Min + (int)(Math.random() * ((Max - Min) + 1))
The Java Math library function Math.random() generates a double value in the range [0,1). Notice this range does not include the 1.
In order to get a specific range of values first, you need to multiply by the magnitude of the range of values you want covered.
Math.random() * ( Max - Min )
This returns a value in the range [0,Max-Min), where 'Max-Min' is not included.
For example, if you want [5,10), you need to cover five integer values so you use
Math.random() * 5
This would return a value in the range [0,5), where 5 is not included.
Now you need to shift this range up to the range that you are targeting. You do this by adding the Min value.
Min + (Math.random() * (Max - Min))
You now will get a value in the range [Min,Max). Following our example, that means [5,10):
5 + (Math.random() * (10 - 5))
But, this still doesn't include Max and you are getting a double value. In order to get the Max value included, you need to add 1 to your range parameter (Max - Min) and then truncate the decimal part by casting to an int. This is accomplished via:
Min + (int)(Math.random() * ((Max - Min) + 1))
And there you have it. A random integer value in the range [Min,Max], or per the example [5,10]:
5 + (int)(Math.random() * ((10 - 5) + 1))
If you look at the implementation of Math.random(), you'll see that it uses an instance of the Random class :
public static double random() {
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
static final Random randomNumberGenerator = new Random();
}
Therefore the randomness would be the same.
That said, since you need an int and not a double, you'd better use the nextInt method of the Random class, since it would save you the multiplication and casting of a double to int.
Random rnd = new Random();
int num = rnd.nextInt(41)+30;
I personally would go with the random class, because, in my opinion, it's way easier to use and to influence with parameters, for example for a random number between 30-79
Random r = new Random(); int i = r.nextInt(40)+30;
I hope that helped at least a bit