How can I generate truly (not pseudo) random numbers with C#?
The answer here has two main sides to it. There are some quite important subtleties to which you should pay due attention...
The Easy Way (for simplicity & practicality)
The RNGCryptoServiceProvider
, which is part of the Crypto API in the BCL, should do the job for you. It's still technically a pseudo-random number generated, but the quality of "randomness" is much higher - suitable for cryptographic purposes, as the name might suggest.
There are other crypographic APIs with high quality pseudo random generaters available too. Algorithms such as the Mersenne twister are quite popular.
Comparing this to the Random
class in the BCL, it is significantly better. If you plot the numbers generated by Random
on a graph, for example, you should be able to recognise patterns, which is a strong sign of weakness. This is largely due to the fact that the algorithm simply uses a seeded lookup table of fixed size.
The Hard Way (for high quality theoretical randomness)
To generate truly random numbers, you need to make use of some natural phenomenon, such as nuclear decay, microscopic temperature fluctuations (CPU temperature is a comparatively conveient source), to name a few. This however is much more difficult and requires additional hardware, of course. I suspect the practical solution (RNGCryptoServiceProvider
or such) should do the job perfectly well for you.
Now, note that if you really do require truly random numbers, you could use a service such as Random.org, which generates numbers with very high randomness/entropy (based on atmospheric noise). Data is freely available for download. This may nonetheless be unnecessarily complicated for your situation, although it certainly gives you data suitable for scientific study and whatnot.
The choice is yours in the end, but at least you should now be able to make an informative decision, being aware of the various types and levels of RNGs.
Creating a true random
DateTime.Now.Ticks
only has a resolution of approximately 16ms, so if you create a Random
with that overload multiple times within a 16ms "slot" they will all be seeded with the same value and therefore you will get the same sequence.
Initialize your Random
outside your loop so that a single Random
sequence is produced, rather than creating it each time within the loop which could result in Randoms
being seeded with the same value and so produce the same sequence.
Update
My previous point that the default constructor initialized Random
with CPU ticks was incorrect, the default constructor actually uses Environment.TickCount which is:
A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.
Which still has a low resolution. If you make multiple instances of Random
in quick succession, they can easily be created within the same time slot and therefore have the same seed value, and create the same sequence. Create a single instance of Random
and use that.
Update
Further to your comments, if you wish to generate a random sequence across multiple threads, please see the following Jon Skeet article which discusses a thread-safe wrapper:
https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness
Random Binary Generator (not pseudo)
function randomInt(max)
// produces integer with uniform distribution between [0,max)
# this should be in your standard library
# though perhaps not by this name; and you may need to
# initialize and maybe randomly seed your RNG beforehand
myRandomBinaryNumber = randomInt(2^10) // then cast it if required
edit: this answer added before "(not pseudo)" added to title
edit: I recommend the methods listed in other answers, depending on one's needs (pseudorandom, cryptographically pseudorandom, truly random, etc.)
Is the C# random number generator guaranteed to be stable?
No, the result from the same seed can vary across versions of the framework, and it's in the documentation here:
The implementation of the random number generator in the Random class isn't guaranteed to remain the same across major versions of the .NET Framework. As a result, you shouldn't assume that the same seed will result in the same pseudo-random sequence in different versions of the .NET Framework.
That documentation also contains variations of this advice in other sections, e.g. in Retrieve the same sequence of random values:
The following example uses 100100 as an arbitrary seed value to instantiate the Random object, displays 20 random floating-point values, and persists the seed value. It then restores the seed value, instantiates a new random number generator, and displays the same 20 random floating-point values. Note that the example may produce different sequences of random numbers if run on different versions of the .NET Framework.
And:
However, note that Random objects in processes running under different versions of the .NET Framework may return different series of random numbers even if they're instantiated with identical seed values.
Randomly generated values are not really random
Random numbers use a seedvalue to start the sequence. If you give nothing, it takes to current datetime.now value. if you supply the same value (like 3842) you will get the same sequence of random values guaranteed. Your series seemed to be very closely related so you see the same values. All this can be read in the documentation on msdn, see Instantiate pseudo random :
Instantiating the random number generator
You instantiate the random number generator by providing a seed value (a starting value for the pseudo-random number generation algorithm) to a Random class constructor. You can supply the seed value either explicitly or implicitly:
The Random(Int32) constructor uses an explicit seed value that you supply.
The Random() constructor uses the system clock to provide a seed value. This is the most common way of instantiating the random number generator.
If the same seed is used for separate Random objects, they will generate the same series of random numbers. This can be useful for creating a test suite that processes random values, or for replaying games that derive their data from random numbers. However, note that Random objects in processes running under different versions of the .NET Framework may return different series of random numbers even if they're instantiated with identical seed values.
Source: https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx#Instantiate
You find more information and even methods to "better" cryptographical random methods linked above the source I cited.
Algorithm to generate a random number? Don't use System.Random
True random numbers can only be generated "outside" a computer, using radioactivity counts and such. Some VIA processors have hardware to do so.
Volume two of The Art of Computer Programming by Don Knuth spends a lot of time discussing exhaustively various pseudo-random number implementations from a mathematical background. Recommended reading.
pseudo random number generation
Create a list with the numbers you want to have, and then randomly select an element from this list and remove it.
Repeat this until your list is empty, and start over again.
This way you will get each number once in n
tries, but their order will be random.
Pseudo Random Number Generator C#
What you want is a randomly "ordered" list, not a randomly "generated" list. This is usually called "Shuffling".
Here's some sample code (not good code by any means, but I made it as close as yours as a sample) to achieve what you want:
static void Shuffle(int[] list)
{
var rnd = new Random();
int n = list.Count();
while (n > 1)
{
n--;
int k = rnd.Next(n + 1);
int value = list[k];
list[k] = list[n];
list[n] = value;
}
}
static void Main(string[] args)
{
int min = 1;
int max = 10;
int [] numbers = new int[max-min];
for (int i = min; i < max; i++)
numbers[i-min] = i;
Shuffle(numbers);
string display = "";
for (int i = min; i < max; i++)
display += " " + numbers[i-min];
Console.Write(display);
}
The result should be something like:
4 9 2 1 3 7 5 8 6
Should work for any min
and max
values (generating as much numbers as there are in-between)
How do I generate a random integer in C#?
The Random
class is used to create random numbers. (Pseudo-random that is of course.).
Example:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
If you are going to create more than one random number, you should keep the Random
instance and reuse it. If you create new instances too close in time, they will produce the same series of random numbers as the random generator is seeded from the system clock.
Related Topics
How to Remove an Xml Element from File
Creating a SQL Server Table from a C# Datatable
Multiple Aggregates/Repositories in One Transaction
Adding or Subtracting Color from an Image in a Picturebox Using C#
How to Avoid Multiple Instances of Windows Form in C#
Do I Need to Lock or Mark as Volatile When Accessing a Simple Boolean Flag in C#
C# Gui Refresh and Async Serial Port Communication
Why Is There Huge Performance Hit in 2048X2048 Versus 2047X2047 Array Multiplication
Could Not Find Installable Isam
What Is the Use of Static Constructors
Dbset.Attach(Entity) VS Dbcontext.Entry(Entity).State = Entitystate.Modified
Merge Multiple Word Documents into One Open Xml
Main: Not All Code Paths Return a Value
Iterating Through the Alphabet - C# A-Caz
Entity-Framework Code Is Slow When Using Include() Many Times