C# Random generation - c#

I have just passed this article online:
C# Corner and C# Corner and his article (a software developer with over 13 years of experience) recommended using System.Random as follows:
private int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
Isn't that would give him the same number every time ??
Edit:
So my question will become: How does Random choose its seed? a constant or current time value?
Thanks

You should only initialize the seed once and then reuse it:
private Random random = new Random();
private int RandomNumber(int min, int max)
{
return random.Next(min, max);
}

It will give the same result when the method will be called often between short time intervals. This is because the Randoms seed is initialized with the current time value.
This is also the reason why many people have problem of kind that random is not random at all.
BTW it is not Math.Random but System.Random
Following your edit, here is some information on how random is initialized. The information comes from the link above.
The random number generation starts
from a seed value. If the same seed is
used repeatedly, the same series of
numbers is generated. One way to
produce different sequences is to make
the seed value time-dependent, thereby
producing a different series with each
new instance of Random. By default,
the parameterless constructor of the
Random class uses the system clock to
generate its seed value, while its
parameterized constructor can take an
Int32 value based on the number of
ticks in the current time. However,
because the clock has finite
resolution, using the parameterless
constructor to create different Random
objects in close succession creates
random number generators that produce
identical sequences of random numbers.

No because new Random() will init with current time as a seed. That said you should still preserve instance of the random and reuse it.

Maybe. Random created without an explicit seed seeds itself based on current time. If you called RandomNumber rapidly enough you'd get the same number occasionally.
Your intuition is correct, however. It's dumb to create a new Random object every time you need a new number. You should create a single instance and use it.

Related

Not jumping into code while not debugging [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 3 years ago.
for (int i = 1; i < 10; i++)
{
number = randomNumber();
if (!straightLine.Contains(number))
{
straightLine.Add(number);
}
}
public static int randomNumber()
{
Random random = new Random();
return random.Next(1, 100);
}
when I debug it works fine but when I run the program it gets 1 random number and that's it. so the problem is that the random Number method is only called once (when I don't debug then it calls it every time)
what can I do?
germi's answer is slightly misleading as it implies that any repeated instantiation of a new Random will produce the same sequence of values. This isn't quite correct, because your debug code works as you expect.
The documentation for Random says that the Random number generator is seeded from the system clock if you dont pass a seed value. https://learn.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8
The reason it works in debug is that debugging code is very slow (you're literally taking hundreds of milliseconds to step through the code a line at a time) and the clock has time to change in between runs of the loop.
When your code is run at full speed it runs so quickly that the system clock simply won't have changed to a new milliseconds value, so your repeated making of a new Random will result in it being seeded with the same value from the clock
If you were to insert some delay in the code such as Thread.Sleep(1000) in the loop then it would work. If you were to run the loop a million times it would take long enough to work through that the clock would eventually change - a million iterations might take long enough for a small handful of values to come out of the Random
The recommendation for a solution is sound though; make one new Random somewhere outside of the loop and then repeatedly call it. You could also seed the Random with something that is unique each time (like the value of i), though you should bear in mind that providing a particular seed will guarantee that the same random number comes out of it when you call Next. In some contexts this is useful, because you might want a situation where you can provide a certain value and then see the same sequence of random numbers emerge. The main thing to be mindful of is that by default the Random starts it's sequence based on the clock; two different computers with different time settings can theoretically produce the same random numbers if their clocks are reading the same at the moment the Random is created.
Repeatedly instantiating a new Random instance will lead to the same number being generated, since the seed will be the same.
The solution is to have one instance of Random in the class that generates the values:
var random = new Random();
for (int i = 1; i < 10; i++)
{
number = random.Next(1,100);
if (!straightLine.Contains(number))
{
straightLine.Add(number);
}
}
Note that this behavior only exists in .NET Framework, .NET Core will produce different values even across multiple Random instances created in quick succession.

Randomly generated values are not really random

I am making a simple game in C# and using Random class to generate a random number every 2 seconds, but it gives numbers that I can guess in advance because it increments by a certain number each time.
private int RandomNumber;
//This Timer function runs every 2 seconds
private void TmrGenerateRandomNum(object sender, EventArgs e)
{
Random r = new Random();
RandomNumber = r.Next(50, 200); //Trying to get random values between 50 and 200
Label1.Text = RandomNumber.ToString();
}
This is literally the only code I have, and I am displaying the value each time through Label1. The problem is, for example, if I first get 52, the next "randomly"-generated value is 71 or 72, and the next one is 91 or 92, and the next one is 111 or 112. As you can see, it is incrementing by 20ish. Then it suddenly gets a real random value again like, say, 163. But then the next generated number is 183, again incremented by 20. Since 183+20 exceeds the range, it gets a real random value again, say 83. But the next number generated is again 103, or 104, and then 123 or 124...
This is not "Random" because you can tell around what number the next one is going to be... and this is driving me crazy.
Do you know why it does this, and is there a fix for this?
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.
While true random numbers are relatively difficult to generate, you should be able to get much better results than you are. The problem you're likely having right now, as suggested by comments, is that you should not be "starting over" every time the function is called. As a test, you can try passing some value like 5 as a parameter to the Random constructor. Then you will notice your results are really not random. To fix this, as the comments suggest, you should move the construction of the Random object somewhere global so that the randomness can "build" on itself over time instead of always being reset. Once you confirm that you can get different values with repeated calls, then remove the parameter to the Random constructor so that you don't get the same sequence of random numbers every time you restart your program.
More of an in-depth explanation:
Basically, it's pretty much impossible to generate truly random values in a computer, all of the random values you get are pseudo random and are based off of values like:
User input, like how many keys were pressed in the last 2 minuts
Memory usage, how many KB of memory is being used at this very moment
The most common one: Using the current time in mili seconds to generate a "seed" that's used to generate a series of numbers that are mathematical as randomized as possible
This is where the problem comes from. For example, if you were to have the following code
Random r1 = new Random();
Random r2 = new Random();
Console.WriteLine(r1.next())
Console.WriteLine(r2.next())
Miraculously, you will always get the same number from r1 and r2 despite them being two separate instances. It's because the code block is execute in a time window of <1 ms, which gives these two random number generators the same seed, thus they will generate the same list of numbers.
In your case, the number generator is instantiated every 2 seconds, thus they get an incrementing seed. It's hard to say if that will result in an incrementing starting number, but it might be a start.
So instead, try initializing a single Random() and always call the .next() function on it, and you should be getting a much more random list of numbers
The best you can do is use a CPRNG or Cryptograph Psudo Random Number Generator, it does not need to be seeded by tyhe user and in generally continnualy updates with system events.
To generate a cryptographically secure random number use the RNGCryptoServiceProvider class or derive a class from System.Security.Cryptography.RandomNumberGenerator.
See MSDN Random Class.

Why Random makes same selection always? [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
When I executes the following code I'm getting the same color selected always.
static void Main(string[] args)
{
string[] Colors = new string[10] { "Red", "Yellow", "Green", "Blue", "Purple", "White", "violet", "orange", "indigo", "blue" };
for (int i = 0; i < 13; i++)
{
Random rnd = new Random();
int code = rnd.Next(0, 9);
string Color = Colors[code];
Console.WriteLine(Color);
}
Console.ReadLine();
}
But if ` Random rnd = new Random();' is created outside the loop, then the result is unique. If the loop executes in faster rate then the output will be the same. Suppose I do some Database insert operation in the for loop the result will be a different one (a random one)(step by step execution using break points will also result random selection).
Is it really impossible to supply different seeds for such a small duration?
Random uses current time as a seed. When you create it in loop, it happens so fast that time stays the same for every creation. So seed is the same, and values, generated by Random will be the same too.
Try make random object a static member:
private static Random rnd = new Random();
This prevents building several random objects with a same seed (current time), and prevents producing a same sequence of numbers.
Your loop initializes a new instance of Random with the same seed (current time) upon each iteration. Each instance contains a sequence of various random numbers. The code uses the first number from the sequence, and after the iteration is finished the random object is thrown away, and a new Random object is instantiated. Since the code has been run quite fast, the next random object is created at the same time as the previous one, therefore it has the same seed as that one. The new object contains a sequence of various numbers, but the sequence is the same as the previous one (i.e., they have a same first number, second number, and so forth). Again the code uses the first number from the very same sequence, which results in repetitive numbers.
If you make the Random object a static member, the random sequence is created once, and the code will use the next number (not always the first number) of that sequence, hence you will iterate through the sequence of various random numbers.
If you don't want to make the random object a static member, try to feed its constructor a unique seed. You can make use of your loop variable for this purpose.
If you don't provide a seed, Random will use Environment.TickCount for a seed. In a short loop like this, it's entirely possible that the the whole loop is executed in one tick. So the seed is the same every time, hence your "random" number is, too.
Just use the same random object for the entire loop.
Random is not random in computer programming ;) You can make it "more" random by including a seed or by having a static object containing the random :)
you need to keep the same random object for the reason below:
Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a definite mathematical algorithm is used to select them, but they are sufficiently random for practical purposes.
The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated.
http://msdn.microsoft.com/en-gb/library/system.random.aspx

Die Roller with user selecting number of sides

I'm new to programming and I'm trying to build a die roller game in C#.
The program asks the user for the number of sides and then rolls a dice with a random number.
I have the following pseudocode:
ask user for the number of sides.
roll the die with a random number with max range being the number of sides.
tell the user the number rolled
My question is how do I roll the dice with generating a random number in range specified by the user?
The System.Random class is commonly used to generate casual random numbers.
It has an overload of a method called Next which generates a random integer that is greater than or equal to 0 and strictly less than the passed integer argument.
Thus if the user chooses an n-sided die, and you have an instance of Random r,
r.Next(n) + 1
will generate a random integer between 1 and n inclusive.
It is good practice to create a single instance of Random and reuse it, because if you create several instances close together they will all generate the same numbers.
Random random = new Random();
int randomNumber = random.Next(1, userInput);
One thing for you to know though is the random function isn't exactly random, its random but in the same random order everytime.. I'll let you look on your favourite search engine for seeding ;)
To get a Random integer between 0 and 100 with 100 not included:
Random random = new Random();
int randomNumber = random.Next(0, 100);
System.Random, specifically System.Random.Next(Int32, Int32) should get you started.
Random.Next(Int32, Int32)
Returns a random number within a specified range.
public int RollDice(int iNoSides)
{
var rand = new Random();
return rand.Next(iNoSides) + 1
}
A simple google of random number c# would of got you more or less this exact code.
EDIT
You have the link to the MSDN documentation from other answers and comments, I know your new to programming but the best way to learn is to try as hard as you can to get something. If you get to a state where your mind can't function any more, posting your attempt with your question on Stack will make people generally a lot happier that they are genuinely helping somebody that is stuck
EDIT 2
Following #Rawling's comment, I realised that the overload of the method states that Next(n) returns a Non-negative number less than the specified maximum.

How to seed GUID generation?

What would be the easiest way to code a function in .NET to generate a GUID based on a seed so that I can have greater confidence about its uniqueness?
string GenerateSeededGuid(int seed) { /* code here */ }
Ideally, the seed would come from CryptGenRandom which describes its random number generation as follows:
The data produced by this function is cryptographically random. It is
far more random than the data generated by the typical random number
generator such as the one shipped with your C compiler.
This function is often used to generate random initialization vectors
and salt values.
Software random number generators work in fundamentally the same way.
They start with a random number, known as the seed, and then use an
algorithm to generate a pseudo-random sequence of bits based on it.
The most difficult part of this process is to get a seed that is truly
random. This is usually based on user input latency, or the jitter
from one or more hardware components.
With Microsoft CSPs, CryptGenRandom uses the same random number
generator used by other security components. This allows numerous
processes to contribute to a system-wide seed. CryptoAPI stores an
intermediate random seed with every user. To form the seed for the
random number generator, a calling application supplies bits it might
have—for instance, mouse or keyboard timing input—that are then
combined with both the stored seed and various system data and user
data such as the process ID and thread ID, the system clock, the
system time, the system counter, memory status, free disk clusters,
the hashed user environment block. This result is used to seed the
pseudorandom number generator (PRNG). [...] If an application has access to a good random source, it can
fill the pbBuffer buffer with some random data before calling
CryptGenRandom. The CSP then uses this data to further randomize its
internal seed. It is acceptable to omit the step of initializing the
pbBuffer buffer before calling CryptGenRandom.
tldr; use Guid.NewGuid instead of trying to invent another "more random" approach. (The only reason I can think of to create a UUIDvX from a seed is when a predictable, resettable, sequence is desired. However, a GUID might also not be the best approach2.)
By very definition of being a finite range - 128bits minus 6 versioning bits, so 122 bits of uniqueness for v4 - there are only so many (albeit supremely huge number! astronomically big!) "unique" identifiers.
Due to the Pigeonhole Principle there are only so many Pigeonholes. If Pigeons keep reproducing eventually there will not be enough Holes for each Pigeon. Due to the Birthday Paradox, assuming complete randomness, two Pigeons will try to fight for the same Pigeonholes before they are all filled up. Because there is no Master Pigeonhole List1 this cannot be prevented. Also, not all animals are Pigeons3.
While there are no guarantees as to which GUID generator will be used, .NET uses the underlying OS call, which is a GUIDv4 (aka Random UUID) generator since Windows 2k. As far as I know - or care, really - this is as good a random as it gets for such a purpose. It has been well vetted for over a decade and has not been replaced.
From Wikipedia:
.. only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. The probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs.
1 While there are still a finite set of Pigeonholes, UUIDv1 (aka MAC UUID) - assuming unique time-space - is guaranteed to generate deterministically unique numbers (with some "relatively small" theoretical maximum number of UUIDs generated per second on a given machine). Different broods of Pigeons living in different parallel dimensions - awesome!
2 Twitter uses Snowflakes in parallel dimensions in its own distributed Unique-ID scheme.
3 Rabbits like to live in Burrows, not Pigeonholes. The use of a GUID also acts as an implicit parallel partition. It is only when a duplicate GUID is used for the same purpose that collision-related problems can arise. Just think of how many duplicate auto-increment database primary keys there are!
All you really need to do in your GenerateSeededGuid method is to create a 128-bit random number and the convert it to a Guid. Something like:
public Guid GenerateSeededGuid(int seed)
{
var r = new Random(seed);
var guid = new byte[16];
r.NextBytes(guid);
return new Guid(guid);
}
This is a bit old, but no need for a random generator. But yes this is usefull for testing purpose, but not for general uses
public static Guid GenerateSeededGuid<T>(T value)
{
byte[] bytes = new byte[16];
BitConverter.GetBytes(value.GetHashCode()).CopyTo(bytes, 0);
return new Guid(bytes);
}
public static Guid SeededGuid(int seed, Random random = null)
{
random ??= new Random(seed);
return Guid.Parse(string.Format("{0:X4}{1:X4}-{2:X4}-{3:X4}-{4:X4}-{5:X4}{6:X4}{7:X4}",
random.Next(0, 0xffff), random.Next(0, 0xffff),
random.Next(0, 0xffff),
random.Next(0, 0xffff) | 0x4000,
random.Next(0, 0x3fff) | 0x8000,
random.Next(0, 0xffff), random.Next(0, 0xffff), random.Next(0, 0xffff)));
}
//Example 1
SeededGuid("Test".GetHashCode());
SeededGuid("Test".GetHashCode());
//Example 2
var random = new Random("Test".GetHashCode());
SeededGuid("Test".GetHashCode(), random);
SeededGuid("Test".GetHashCode(), random);
This method is based on php v4 uui https://www.php.net/manual/en/function.uniqid.php#94959

Categories