From:https://www.xcode.me/more/net-csharp-generate-random

The random number generation method can be said to be any programming language necessary function, it's important to say, in C # We usually use the random class to generate stochastic numbers, in some scenarios, I found that the random number generated by randomness is not reliable, in the following example we randomly generated 5 random numbers:

for ( i = 0; I < 5; i++) {random Random = new random (); console . WriteLine (random. Next ()); }

The result of this code execution is as follows:

2140400647 2140400647 2140400647) 2140400647 2140400647

The above results indicate that the random number class generates 5 identical numbers, which is not our expectation, why? In order to understand this problem, the zero analysis of Microsoft's official open source random class, found in C # generated by the use of the algorithm is linear with congruential, by the encyclopedia, this algorithm is not absolute random, but a pseudo-random number, linear with the congruential algorithm is the formula:

Number of n+1 = (Nth number * A + B)% M

In the above formula A, B and M are constants, which are the factors that generate the random number, and if the random number has never been generated by the same arbitrary object (that is, the next method is called), then the nth random number is specified as a default constant. This constant is specified by default when creating a random class, and random also provides a constructor that allows developers to use their own random number factor, which can be seen through Microsoft's official open source code:

public Random (): this (environment . TickCount) {} public Random (int Seed) {}

When you create the random class by using the default constructor, A Environment.tickcount object is passed by default as a factor to the second constructor, Environment.tickcount indicates the number of milliseconds elapsed after the operating system starts, and the computer's operation is much faster than the millisecond, which results in a millisecond-precision factor that participates in the birth of a random number. Process, but in 5 cycles, we use the same millisecond factor to generate the same random number, and the number of n+1 is directly related to the number of nth.

In the above example, assume that the number of milliseconds since the system started is 888 milliseconds, It takes only 0.1 milliseconds to execute 5 cycles, which causes the 5 random objects created in the loop to use the same 888 factor, and each time the random object being created uses the same nth number (the default is constant), it is not difficult to see that the result above is inevitable.

Now we're changing the pattern, creating a random object outside of the loop, referencing it in each loop, and generating a random number from it, and calling the next method multiple times on the same object, changing the nth number as follows:

random Random = new random (); for (console . WriteLine (random. Next ()); }

The results after execution are as follows:

391098894 1791722821 1488616582) 1970032058 201874423

We see that the result does confirm our inference that the number of nth in the formula in the 1th cycle is the default constant, and when the second loop, the nth number is 391098894, then the changing nth number is counted as a factor, which guarantees the randomness of the result.

Although our random number seems to be random, but this algorithm is a pseudo-random number, when the nth number and factor are all the same, the generated random number is still a repeating random number, because random provides a parameter with the constructor allows us to pass a factor, if the incoming factor randomness strong, The generated random number is also more reliable, in order to provide a reliable point factor, we usually use a GUID to generate a fill factor, also put in the loop test:

for(inti = 0; I < 5; i++) {byte[] buffer =Guid. NewGuid (). Tobytearray ();intISeed =Bitconverter. ToInt32 (buffer, 0);RandomRandom =NewRandom(ISeed);Console. WriteLine (random. Next ()); }

This way guarantees the randomness of the fill factor, so the resulting random number is also more reliable, and the result is as follows:

734397360 1712793171 1984332878) 819811856 1015979983

In some scenarios such random numbers are unreliable, in order to generate more reliable random numbers, Microsoft provides a class named RNGCryptoServiceProvider under the System.Security.Cryptography namespace, which takes the system's current hardware information, process information, thread information, The system startup time and the current exact time as a fill factor, with better algorithms to generate high-quality random numbers, it is used as follows:

new byte [4]; rngcryptoserviceprovider rngserviceprovider = new rngcryptoserviceprovider (); Rngserviceprovider.getbytes (randombytes); int32 result = bitconverter . ToInt32 (randombytes, 0);

The random number generated by this algorithm, after thousands of tests, did not find repetition, the quality is indeed much higher than the random. In addition, the Windows API also provides an unmanaged random number generation function Cryptgenrandom,cryptgenrandom similar to the RNGCryptoServiceProvider principle, written in C + +, if you want to. NET, it needs to be packaged in a simple package. Its prototype is as follows:

BOOL WINAPI cryptgenrandom ( _in_ Hcryptprov Hprov, _in_ DWORD dwlen, _inout_ BYTE *pbbuffer );

The above is zero for you to bring the random number generation method and basic principles, you can choose the best way through the requirements and scenarios, the random algorithm is simple, high performance, applicable to the situation of low randomness requirements, Since RNGCryptoServiceProvider needs to query several of the system factors mentioned above during generation, the performance is slightly weaker than that of the random class, but the stochastic number is high quality and reliability is better.

Why are random numbers generated in C # not random?