Is there a better way to generate 3 digit random number than the following:
var now = DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture);
string my3digitrandomnumber = now.Substring(now.Length - 7, 3);
Thanks..
Yes - your current code isn't random at all. It's based on the system time. In particular, if you use this from several threads at the same time - or even several times within the same thread in quick succession - you'll get the same number each time.
You should be using Random or RandomNumberGenerator (which is more secure).
For example, once you've got an instance of Random, you could use:
int value = rng.Next(1000);
string text = value.ToString("000");
(That's assuming you want the digits as text. If you want an integer which is guaranteed to be three digits, use rng.Next(100, 1000).)
However, there are caveats around Random:
You don't want to create a new instance each time you use it; that would also be time based unless you specify a seed
It's not thread-safe
So ideally you probably want one per thread. My article on randomness talks more about this and gives some sample code.
int r = (new Random()).Next(100, 1000);
You can use the Random class and call Next(10) three times.
Well, firstly that's an odd setup you have there, why do you first get the date?
You should use this to get a number of 3 digits (less than 1000).
Random rand = new Random(); // <-- Make this static somewhere
const int maxValue = 999;
string number = rand.Next(maxValue + 1).ToString("D3");
The maxValue + 1 is because the paramter for Random.Next(int) is an exclusive upper bound, meaning that the number returned will always be less than the parameter. It can never be equal to it.
new Random.NextDouble() * 1000
Related
I've had a chance to see some interesting piece of code that was either used as an April Fools joke (update became public on April 1st) or was just a bug, because someone did not understand how to use RNGs.
Question is related to Random class being part of .NET/C#, but maybe other RNGs work the same way.
Simplified version of the code I found, after taking out all the unnecessary details, would look like this:
for ( int i = startI; i < stopI; ++i ) {
int newValue = new Random( i ).Next( 0, 3 ); // new RNG with seed i generates a single value from 3 options: 0, 1 and 2
// rest of code
}
I did run simple test of that code in LINQPad to see if what I was observing in program was just my "luck" or whether maybe that's actually how RNG used this way will work. Here's the code:
int lastChoice = -1;
int streakLength = -1;
for ( int i = 0; i < 100000000; ++i ) {
int newChoice = new Random( i ).Next( 0, 3 );
if ( newChoice == lastChoice ) {
streakLength++;
( i + ";" + lastChoice + ";" + streakLength ).Dump();
} else {
lastChoice = newChoice;
streakLength = 1;
}
}
"The End".Dump();
(The Dump() method simply prints the value to the screen)
The result of running this "script" was just "The End", nothing more. It means, that for 100M cycles of generating a random value, not a single time was it able to generate same consecutive values, when having only 3 of them as an option.
So back to my question from the title - does increasing the seed of RNG (specifically the .NET/C#'s Random class, but general answer is also welcome) by one after every (integer) random number generation would ensure that no repeated consecutive values would occur? Or is that just pure luck?
The behavior you show depends on the PRNG.
For many PRNGs, including linear PRNGs such as the one implemented in the .NET Framework's System.Random, if you initialize two instances of a PRNG with consecutive seeds, the number sequences they produce may be correlated with each other, even though each of those sequences produces random-behaving numbers on its own. The behavior you describe in your question is just one possible result of this.
For System.Random in particular, this phenomenon is described in further detail in "A Primer on Repeatable Random Numbers".
Other PRNGs, however, give each seed its own independent pseudorandom number sequence (an example is SFC64 and counter-based PRNGs; see, e.g., "Parallel Random Numbers: As Easy as 1, 2, 3"), and some PRNGs can be "jumped ahead" a huge number of steps to produce pseudorandom number sequences that are independent with respect to each other.
See also:
Impact of setting random.seed() to recreate a simulated behaviour and choosing the seed
Seeding Multiple Random Number Generators
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 8 years ago.
I know there are multiple times this question has been put forth but none of those solutions worked for me.
First I did this in my method called RandomNumGenerator(items)
List<int> randNum = new List<int>();
foreach (var item in items)
{
randNum.Add(new Random(1000).Next());
}
This always gave me the same number, and then after looking at this answer I did this:
Random rnd = new Random(1000);
foreach (var item in items)
{
randNum.Add(rnd.Next());
}
This gave me the numbers as below
325467165
506683626
1623525913
2344573
1485571032
Now while that is fine for every iteration of the loop, the problem here is, when I stop and re-run the application, I get the same numbers I got earlier all over again.
325467165
506683626
1623525913
2344573
1485571032
Is this behavior during debugging only or will I have the same issue every time I call the RandomNumGenerator?
You are seeding the Random instance always with the same seed 1000 here:
Random rnd = new Random(1000);
this will not do that since the current time is used as seed:
Random rnd = new Random();
Have a look at the constructor which takes an int.
Providing an identical seed value to different Random objects causes
each instance to produce identical sequences of random numbers.
As per MSDN.
public Random(
int Seed
)
Seed
A number used to calculate a starting value for the pseudo-random number sequence. If a negative number is specified, the absolute value of the number is used.
The reason for most beginner's mistakes involving RNGs (random number generators), is the lack of understanding about what the "seed" is and what it does.
So what is a "seed"?
The Random class is a class for generating pseudo-random numbers - or numbers that appear to be random. They are usually a mathematical function, that uses a parameter - the "seed" - to generate a sequence of numbers that appear to be random.
In the case of new Random(1000), the first 5 nonnegative random integers are
325467165
506683626
1623525913
2344573
1485571032
In your first code, you create a new sequence of pseudo-random numbers with the same seed every time you need a random number, so obviously your array is filled with the same number: 325467165, which happens to be the first nonnegative integer generated by new Random(1000).
This also explains why your second code always generates the same sequence of pseudo-random numbers every time your application is launched.
To ensure your app always generate different pseudo-random sequences, you need to use a different seed each time. By far the easiest way to ensure that, is to take your time, literally.
Random rnd = new Random(DateTime.UtcNow.Millisecond);
// Taking the millisecond component, because it changes quickly
Luckily, you don't have to type this much, because the default constructor for the Random class already does something similar to that.
Random rnd = new Random(); // Much simpler, isn't it?
Keep in mind that the Random class is not thread safe; if multiple threads attempt to access the same Random object concurrently, your RNG will return only 0 for the remaining of its lifetime.
Another thing to note, is that creating multiple Random objects one after the other - even when using time as the seed - can lead to the same sequence of pseudo-random numbers.
Random r1 = new Random();
Random r2 = new Random();
Random r3 = new Random();
Random r4 = new Random();
In the above code, chances are very high, that r1, r2, r3 and r4 will all generate the same sequence.
How is that possible?
Well, (un)fortunately, CPUs are blazing fast. A 1 GHz CPU can execute about 1 billion instructions per second (give or take); that's 1 instruction every 1 nanosecond - or 1 instruction every 1 millionth of a millisecond.
Creating a new Random object might require quite a lot of instructions, but most definitely less than a million of them.
So why do we need to manually define a seed, if using the clock's current millisecond count is what we "all" want and is already the default?
Because it can be very useful for keeping multiple terminals in sync.
Imagine a game, where important phenomena randomly appear, such as a change in weather that could completely overturn the game. You wouldn't want only one side to suffer from fog, while the rest still profits from clear weather, right?
Of course, you could have the server or the host generate random weather changes and notify the players about it; or you could define a seed before the game starts, and use that seed to ensure the same "randomness" across all players throughout the game.
Isn't coding fun?
You need to change this:
Random rnd = new Random(1000);
to
Random rnd = new Random();
From the Random Constructor docs:
The default seed value is derived from the system clock and has finite
resolution. As a result, different Random objects that are created in
close succession by a call to the default constructor will have
identical default seed values and, therefore, will produce identical
sets of random numbers. This problem can be avoided by using a single
Random object to generate all random numbers. You can also work around
it by modifying the seed value returned by the system clock and then
explicitly providing this new seed value to the Random(Int32)
constructor. For more information, see the Random(Int32) constructor.
Key concept is random seed - the initial piece of data from which the Random derives everything else. If the seed is the same then "random" sequence will be the same.
By default the seed is set to zero, which obviously leads to repeating sequences amongst program runs.
To avoid that, you can construct your Random like this:
Random rnd = new Random();
... which is, under the hood, is:
Random rnd = new Random(Environment.TickCount);
This will init the Random object with amount of milliseconds from the OS start. This will be different each time your program starts, so you'll get different random sequences each time.
Random .Next() method generates pseudo-random number. You should Declare and initialize a random object instead of creating each time new object. And no need to use any Cryctography .. :)
You should use class level random variable. If you used a new Random at the method level as a local , the time-dependent seed would repeat itself generating identical sequence of random numbers.
class Program
{
static Random _r = new Random();
static void Main()
{
// use _r variable to generate random number
}
}
is there any good method to generate random even numbers with C#? I came up with this code:
Random RandString = new Random(0);
code:
private void button6_Click(object sender, EventArgs e)
{
int min = 0;
int max = 50;
int rand = RandString.Next(min, max-1);
while (rand % 2 == 1) // odd
{
rand = RandString.Next(min, max-1);
}
textBox4.Text = "" + rand;
}
Problems with this code:
my current solution might not be the fastest of all
very often, numbers that are generated by this method are repeated with the same sequence! For example after 5 iterations I can get: 8, 10, 20, 30, 16. After more clicking (for like 15 seconds) I can get 10, 30, 20 in a row or 30, 20, 10.. I'm not sure, but that's NOT what I call "random".
so is there any way to deal with the problem that I've described, or is there any other method?
textBox4.Text = (2 * rand.Next(min / 2, max / 2)).ToString();
even easier would be to take your result and multiply it by 2
private void button6_Click(object sender, EventArgs e)
{
int min = 0;
int max = 25;
int rand = RandString.Next(min, max-1)*2;
textBox4.Text = rand.ToString();
}
Random random = new Random();
int nextnum = random.Next(min/2,max/2) * 2
You could use the RNGCryptoServiceProvider to get a "more random" (which is a silly term I admit) number. There is a nice eample on MSDN's documentation page.
As others recommended, you can just multiply the result with 2 to get an even number.
There are a number of flaws in your approach.
First of all, Random from .NET isn't completely random in the cryptographic sense AFAIK, but it should be much much better than the results you report. Most likely, you are creating a new Random object on every iteration of your loop; since the current system time is used to seed the RNG, you will get the same sequences of pseudo-random numbers if you do runs very short after one another. Instead, create one instance of Random at startup, and keep it around for as long as possible.
Then, creating an even number from a random integer is much easier than looping until you find one that happens to be even: just generate one random number and clear the least significant bit: myRand.Next(min, max-1) & ~1;. A decent RNG has a uniform distribution over all of its bits, so clearing any bit shouldn't reduce entropy by more than, well, one bit.
Getting back to the 'completely random' part: Random provides a pseudo-random number generator. It is seeded once, based on a value that is somewhat random-ish (the least-significant parts of the current system time), but given the same seed, the RNG will reliably and deterministically produce the same numbers on every run. If you want true randomness (a.k.a. 'entropy'), you'd be surprised how hard it is to produce it on a machine that was built for deterministic calculations. UNIX and Unix-like systems typically offer a pool of entropy through a special kernel-generated file (/dev/random), using things like hard disk access timing, network noise, and whatever other sources of actual randomness they can find, and distillate those into a uniform distribution using fairly complicated calculations. Windows can probably do the same, but I am unaware of any API for this in either .NET or the classic win32 API.
How to generate 6 dig random number (within specific interval)? would
Random rand = new Random();
still work in this case? (e.g rand.Next(000000, 000101)) I need to keep 6dig format
asp.net C#
You need to separate the numeric value from the text representation. 000101 is the same number as 101. Pick the random number using Next(min, max) and then format it however you want, e.g. with value.ToString("000000") or value.ToString("D6") (whichever you find more readable).
Note that you should take care when using Random - there are a few subtle issues. (In particular, you very rarely want to actually create a new instance with the parameterless constructor in the line of code before you use it...)
Try this:
string.Format("{0:000000}", rand.Next(0, 100));
A number doesn't have a format at all, you give it a format when you convert the number to a string. So, the random part of the code is the same, you just format the number in a specific way:
Random rnd = new Random();
string formatted = rnd.Next(1, 101).ToString("000000");
Note: The lower bound for the Next method is inclusive and the upper bound is exclusive. Next(0, 101) would give you a result between 000000 and 000100.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why is Random class isn't really random?
I have following kind of code:
public static int GenerateRandomNumber(int seed)
{
var random = new Random(seed);
int num = random.Next();
while(num.ToString().Length != 6){
num = random.Next();
}
return num;
}
I want to get different number every time when call this function even with same seed. But I always got same result.
For example, every time when call GenerateRandomNumber(1), I always got number 640839.
How to fix this problem?
I want to get different number every time when call this function even with same seed.
Since that is the opposite of what the Random constructor is documented to do, you are going to have to learn to live with disappointment. You can't always get what you want.
Here is your problem:
var random = new Random(id);
Random generates a pseudo-random set of results - for the same seed, you would get the same sequence every time.
Change the creation of the Random object to a static field and you will get a different result whenever you call it.
From MSDN - Random Class:
The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated.
Random creates a series of pseudo-random numbers based on an initial value called a seed (id in your code).
Since the seed is identical then all calls to the function will follow the same code-path and generate the same result.
Make the random = new Random(seed) a static variable in your function or make it a member in the containing class and pass it to all functions/classes that need it.
Consider using a time based seed value when you are done developing the program.
I want to get different number every time when call this function even with same seed.
That's not how seeds work. The whole point of a seed is that using the same seed will result in the same series of pseudo-random numbers. The series is deterministic
The problem you need to fix is to align your expectations with the product specifications:
Providing an identical seed value to
different Random objects causes each
instance to produce identical
sequences of random numbers.
So either expect the same sequence froma seed, or don't use a seed.