Preundorandom: Random numbers generated by the algorithm are pseudo-random!!

Only random numbers generated by real random events are truly random!! For example, the hardware noise of the machine generates random numbers, and the atmospheric noise generates random numbers

Random generated Random numbers are pseudorandom numbers!!

Is a pseudorandom number generated by a determinable function (often linear congruence) through a seed (often clock). This means that if we know the seed or the random number that has been generated, we can get the information of the following random number sequence (predictability).

The Random class has two constructors to implement a Random number generator:

1 Random() Constructs a Random number generator, seeded with xor values after nanoTime. Multiple sequences are output differently each time. More randomness.

2 Random(long seed) Construct a Random number generator with the seed. The seed is given. Multiple sequences are the same each time.

Source:

/** * Creates a new random number generator. This constructor sets * the seed of the random number generator to a value very likely * to be distinct from any other invocation of this constructor. */ public Random() { this(seedUniquifier() ^  System.nanoTime()); // xor with system.nanotime () // here system.nanotime (); It's not the system time in nanoseconds, it's just how much time it takes. It has nothing to do with the concept of time. } private static long seedUniquifier() { // L'Ecuyer, "Tables of Linear Congruential Generators of // Different Sizes and Good Lattice Structure", 1999 for (;;) { long current = seedUniquifier.get(); long next = current * 181783497276652981L; if (seedUniquifier.compareAndSet(current, next)) return next; } } private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L); /** * Creates a new random number generator using a single {@code long} seed. * The seed is The initial value of  the internal state of the pseudorandom * number generator which is maintained by method {@link #next}. * * <p>The invocation {@code new Random(seed)} is equivalent to: * <pre> {@code * Random rnd = new Random(); * rnd.setSeed(seed); }</pre> * * @param seed the initial seed * @see #setSeed(long) */ public Random(long) { If (getClass() == random.class)// Random random1 = new Random(); Or Random random2 = new Random(100); Seed = new AtomicLong(initialScramble(seed)); Else {// subclass might have overriden setSeed this.seed = new AtomicLong(); setSeed(seed); } } private static long initialScramble(long seed) { return (seed ^ multiplier) & mask; }Copy the code

I. No-parameter construction method (no seed setting)

The Random constructor has its own seed generation mechanism, although it does not appear to have a seed set.

Seed generation process :(see decrypting random number generator (2) — linear congruence algorithm from Java source code)

1, get a long integer as the “initial seed” (default is 8682522807148012L)

2. Multiply by a perky number, 181783497276652981L, to an unpredictable value, until you can assign this unexpected value to Random’s static constant seedUniquifier. Because assignments can fail in multithreaded environments, for(;;) To make sure the assignment succeeds

3. Perform xOR operation with the nanotime value randomly generated by the system to obtain the final seed

Nanotime is a fairly random parameter that describes the execution time of code. Description of nanotime in the source code (part) :

It’s not the system time in nanoseconds, it’s just how much time it takes. It has nothing to do with the concept of time.

/** * Returns the current value of the running Java Virtual Machine's * high-resolution time source, in nanoseconds. * * <p>This method can only be used to measure elapsed time and is * not related to any other notion of system or wall-clock time. * The value returned represents nanoseconds since some fixed but * arbitrary <i>origin</i> time (perhaps in the future, so values * may be negative). The same origin is used by all invocations of * this method in an instance of a Java virtual machine; other * virtual machine instances are likely to use a different origin. * * <p>This method provides nanosecond precision, but not necessarily * nanosecond resolution (that is, how frequently the value changes) * - no guarantees are made except that the resolution is at least as * good as that of  {@link #currentTimeMillis()}. * * <p>Differences in successive calls that span greater than * approximately 292 years (2<sup>63</sup> nanoseconds) will not * correctly compute elapsed time due to numerical overflow. * * <p>The values returned by this method become meaningful only when * the difference between two such values, obtained within the same * instance of a Java virtual machine, is computed. * * <p> For example, to measure how long some code takes to execute: * <pre> {@code * long startTime = System.nanoTime(); * / /... the code being measured ... * long estimatedTime = System.nanoTime() - startTime; }</pre> * * <p>To compare two nanoTime values * <pre> {@code * long t0 = System.nanoTime(); *... * long t1 = System.nanoTime(); }</pre> * * one should use {@code t1 - t0 < 0}, not {@code t1 < t0}, * because of the possibility of numerical overflow. * * @return the current value of the running Java Virtual Machine's * High resolution time source, in nanoseconds * @since 1.5 */ public static native long nanoTime();Copy the code

2. Parameter construction method (seed setting)

Syntax: Random ran = Random(long seed)

Have parameter constructor source as above.

Where multiplier and mask are constant values:

1  private static final long multiplier = 0x5DEECE66DL;
2 
3  private static final long mask = (1L << 48) - 1;
Copy the code

3. Code testing

Generate random integers within [0, 100) using two methods with and without parameters respectively, and generate five groups of random numbers in each group of ten:

1 import java.util.Random; 2 3 public class RandomTest { 4 public static void main(String[] args) { 5 RandomTest rt = new RandomTest(); 6 rt.testRandom(); 7} 9 9 public void testRandom(){10 system.out.println ("Random "); 11 for (int i = 0; i < 5; i++) { 12 Random random = new Random(); 13 for (int j = 0; j < 10; j++) { 14 System.out.print(" " + random.nextInt(100) + ", "); 15 } 16 System.out.println(""); 17 } 18 19 System.out.println(""); 20 21 system.out. println("Random set seed: "); 22 for (int i = 0; i < 5; i++) { 23 Random random = new Random(); 24 random.setSeed(100); 25 for (int j = 0; j < 10; j++) { 26 System.out.print(" " + random.nextInt(100) + ", "); 27 } 28 System.out.println(""); 29} 30} 31}Copy the code

The running results are as follows:

Conclusion:

** Although both are pseudorandom, the ** parameterless constructor (no seed is set) has stronger randomness and can meet the requirements of general statistical randomness. Use the argument constructor (set the seed) no matter how many times you generate it, the resulting random sequence is the same every time, pseudo random!!

Why use seeds?

Seed is the root of random number generation, is the basis of random number generation. The random number of the computer is pseudo random number, with a true random number (seed) as the initial condition, and then use a certain algorithm to continuously generate random number. Random numbers are usually obtained in Java projects using the math. random method and the random class. The parameterless constructor in the Random class uses the current time as the seed each time, whereas the parameterless constructor uses a fixed value as the seed.

Random numbers are generated by seed computation.

The no-argument constructor uses the current time as a seed each time, making it more random

The generation of random numbers starts with seed values. If the same seed is used over and over again, the same series of numbers will be produced, and one way to produce different sequences is to correlate seed values with time.

Five, the System. NanoTime ()

System.out.println(System.nanoTime()); System.out.println(system.nanotime ())); System.out.println(System.nanoTime()); System.out.println(System.currentTimeMillis()); // First run: // 281092180853691 // 281092180911666 // 281092180936920 // 1610767387212 => 2021-01-16 11:23:07 // second run: 281207286912695 // 281207286952070 // 281207286970745 // 1610767502318Copy the code

The above operation, source code based on JDK1.8

end