Generating random numbers effectively - c#

How do you generate random numbers effectively?
Every time a random number program boots up, it starts spitting same numbers as before. (I guess because of quasi nature of random number generation)
Is there a way, that random# generation becomes non-deterministic? sort of Entropy addition to generation that number generated after boot is in different sequence than last one. (random random rather that quasi-random)
Also, say range of such generation is (m,n) such that n-m = x, is there a chance that a number say 'p' appears next time after x-1 other numbers have been generated. But next lot of such x numbers would not be same as sequence from last one. Example:
range: 1,5. Generation : 2,4,5,1,3 (1st) 4,2,3,1,5 (2nd)... same numbers.
I out of nonplussed state of mind wrote this :
int num1 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;
int num2 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;
here range was (1,440). but it still generates numbers out of bound and zero, and it's frequency is not that great either. It is C#.NET code. Why so?
your answers can be language agnostic / algorithmic / analytical. Thanks in advance.

Very few "random" number generators are actually random. Almost all are pseudorandom, following a predictable sequence when started with the same seed value. Many pseudorandom number generators (PRNGs) get their seed from the date and time of their initial invocation. Others get their seed from a source of random data supplied by the operating system, which often is generated from outside sources (e.g., mouse motion, keyboard activity).
The right way to seed a good random number generator is to not seed it. Every good generator has a default mechanism to supply the seed, and it is usually much better than any you can come up with. The only real reason to seed the generator is if you actually want the same sequence of random numbers (e.g., when you're trying to repeat a process that requires randomness).
See http://msdn.microsoft.com/en-us/library/system.random.aspx for the details of the C# Random class, but basically, it uses a very well known and respected algorithm and seeds it with the date and time.
To answer your key question, just use rand.Next(min, max+1) and you'll always get a random sequence of numbers between min and max inclusive. The sequence will be the same every time you use the same seed. But rand = new Random() will use the current time, and as long as your program is invoked with some separation in time, they'll be different.

"Seed" the random number generator by getting the number of seconds since midnight and then passing it in:
Random rand = new Random(secs);
This still does not generate perfectly random numbers, but should serve your purpose.

Producing the same sequence over and over is often a feature, not a bug, as long as you control it. Producing a repeatable sequence makes debugging easier. If you are serious about wanting a non-reproducible random sequence, you could look for a secure random number generator with this as a design aim. You've tagged your question C#, but since Java has http://docs.oracle.com/javase/1.4.2/docs/api/java/security/SecureRandom.html and the windows API has http://en.wikipedia.org/wiki/CryptGenRandom you may able to find an equivalent in C#.

I am not so conversant in C#.
But I don't think this problem would occur in Java because the default constructor of Random class uses a seed based on current time and a unique count identifier.Below is code from java.util.Random class.
private static volatile long seedUniquifier = 8682522807148012L;
public Random() { this(++seedUniquifier + System.nanoTime()); }
If C# doesent support this out of box, you could use the above code to create a unique seed each time.
P.S: Note that since access to seedUniquifier is not synchronized, even though its volatile, there is a small possibility that same seeds are used for multiple Random objects. From javadoc of Random class:
"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."

You can use a chaotic map to generate random numbers. The C++ code below (GenRandRea) returns a vector of random number using the so-called "Tent map" (https://www.wikiwand.com/en/Tent_map). The seed is an integer that is used to generate x (as a number between 0. and 1.) as input of the iterative map. Diferent seeds will generate different sequences.
vector<double> GenRandRea(unsigned seed, int VecDim){
double x, y, f;
vector<double> retval;
x = 0.5*(abs(sin((double)seed)) + abs(cos((double)seed)));
for (int i = 0; i<(tentmap_delay + VecDim); i++) {
if ((x >= 0.) && (x <= 0.5)) {
f = 2 * tentmap_r * x;
}
else {
f = 2 * tentmap_r * (1. - x);
}
if (i>=tentmap_delay) {
y = (x*tentmap_const) - (int)(x*tentmap_const);
retval.push_back(y);
}
x = f;
}
return retval;
}
with
const double tentmap_r = 0.75; //parameter for the tent map
const int tentmap_delay = 50; /*number of interactions in the tent map
allowing for sorting */
const double tentmap_const = 1.e6; //constant for the tent map
VecDim is the output vector dimension. The ideia is to iterate at least (tentmap_delay + VecDim) turns and write the result in retval (a vector of doubles).
To use this code:
vector<double> val;
val = GenRandRea(2, 10);
for (int kk=0; kk<10;kk++){
cout << setprecision(9) << val[kk] << endl;
}
which will for example produce:
0.767902586
0.848146121
0.727780818
0.408328773
0.88750684
0.83126026
0.253109609
0.620335586
0.569496621
0.145755069
Regards!

Related

Getting a 0.5% chance in C#

As I new to C# I don't really want to mess around with the Random() for a long time trying to get what I want, and I also want to know it does what I need it to do without giving it a really long amount of time in testing. How can I get a 0.5% chance of something (1/200) with a random? would this code would? How random is Random really.. this isn't a question of "how random is random" so don't go posting duplicates, but its a question on how I can do this.
My question is not "How random is Random, its if this code is the best way to do the job, and will it achieve what I am trying to achieve."
var random = new Random();
var randomNumber = random.Next(1, 200);
if (randomNumber == 87)
{
// I can put any number inbetween 1 and 200, will this work?
// If we reach this if statement we have got a 0.5 chance?
}
Firstly you should convert your chance into a normalized value between 0.0 and 1.0. This is the mathematical notion of a probability.
For your case, this would give you double probability = 0.005;.
Then you can do the following:
if (rng.NextDouble() < probability)
{
...
This works because Random.NextDouble() returns a random number evenly distributed within the half-open interval [0.0, 1.0) (i.e. up to but not including 1.0.)
So if your probability is 0.0 the body of the if will never be executed, and if your probability is 1.0 then it will always be executed.
The advantage of using a normalised probability is that it works with any probability, and not just with integral probabilities.
If you do happen to have a percentage probability, you convert it to a normalised one very simply - by dividing it by 100.0.
Addendum:
There's little advantage to using Random.Next(int min, int max) instead, because that only works for integral probabilities. And behind the scenes, Random.Next(int min, int max) is implemented like this:
public virtual int Next(int minValue, int maxValue) {
if (minValue>maxValue) {
throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
}
Contract.EndContractBlock();
long range = (long)maxValue-minValue;
if( range <= (long)Int32.MaxValue) {
return ((int)(Sample() * range) + minValue);
}
else {
return (int)((long)(GetSampleForLargeRange() * range) + minValue);
}
}
And NextDouble() is implemented as:
public virtual double NextDouble() {
return Sample();
}
Note that both these implementations call Sample().
Finally I just want to note that the built-in Random class isn't particularly great - it doesn't have a very long period. I use a RNG based on a 128-bit XOR-Shift which is very fast and generates very "good" random numbers.
(I use one based on this XORSHIFT+ generator.)

Random.Next returns always the same values [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
I use the method to generate unique number but I always get the same number -2147483648. Even if I stop the program, recompile it and run again I still see the same number.
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
var random = new Random();
return random.Next((int)min, (int)max);
}
Try externalizing the random instance:
private readonly Random _random = new Random();
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
return _random.Next((int)min, (int)max);
}
This is not an issue of not reusing Random instance, the results he gets should be random on multiple starts, not always being -(2^32)
This is the issue with length being too big, and casting powers of length to int. If you break the code into following lines:
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
var random = new Random();
var a = (int)min;
var b = (int)max;
return random.Next(a, b);
You'll see that a and b are -2147483648, making that the only possible result of Next(min, max) (the doc specifies if min==max, return min).
The largest length you can safely use with this method is 9. For a length of 10 you'll get System.ArgumentOutOfRangeException, for length > 10 you'll get the -2147483648 result.
You have three problems with your code.
You should externalize your random variable.
You have a problem with truncation error.
The range between min and max is way to large.
The first problem is because you may not have enough time to advance the seed when reinitializing your random variable. The second error comes from truncating your (what would b very large) numbers down to ints. Finally, your biggest problem is your range between your min and your max. Consider finding the range between min and max (as defined in your code) with inputs 1->20:
length max-min
1 8
2 89
3 899
4 8999
5 89999
6 899999
7 8999999
8 89999999
9 899999999
10 8,999,999,999
11 89999999999
12 899999999999
13 8999999999999
14 89999999999999
15 899999999999999
16 9E+15
17 9E+16
18 9E+17
19 9E+18
And keep in mind that the maximum integer is 2,147,483,647, which is passed on any number greater than 9.
You should keep an instance of Random and not new() it up all the time, that should give you better results.
Also check for what length actually is. It may be giving you funny results as to the limits.
I think the problem is the calculation of min and max. They will be greater than Int32.MaxValue pretty fast...
In your class, have one instance of Random, e.g.:
public class MyClass
{
private readonly Random random = new Random();
public static int GetRandomInt(int length)
{
var min = Math.Pow(10, length - 1);
var max = Math.Pow(10, length) - 1;
return random.Next((int)min, (int)max);
}
}
The fact that random always returns the same values only exists for testing purposes.
Random classes usually use a seed to initialize themselves, and will usually return the same sequence provided the seed is the same one :
Always reuse the same Random() instance instead of recreating one over and over again
if you want unpredictable results, use a time-dependent seed rather than an hard-coded one
It's very difficult to code a truly random number generator. Most methods use external entropy generators (such as mouse movement, cpu temperature, or even complex physical mechanisms such as helium balloons colliding one another...).
The Random instance should be created only once and then reused. The reason for this is that the RNG is by default seeded with the current system time. If you rapidly create new Random instances (and pull one value from it) then many of them will be seeded with the same timestamp, because the loop probably executes faster than the system clock advances.
Remember, a RNG initialized by seed A will always return sequence B. So if you create three Random instances all seeded with for example 123, these three instances will always return the same number on the same iteration.

C#/Java Number Randomization

Is it possible, from .NET, to mimic the exact randomization that Java uses? I have a seed, and I would like to be able to recieve the same results in both C# and Java when creating a random number.
You don't need to read the source code. The formula is a one-liner and is given in the documentation for java.util.Random.
Here's a partial translation:
[Serializable]
public class Random
{
public Random(UInt64 seed)
{
this.seed = (seed ^ 0x5DEECE66DUL) & ((1UL << 48) - 1);
}
public int NextInt(int n)
{
if (n <= 0) throw new ArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)Next(31)) >> 31);
long bits, val;
do
{
bits = Next(31);
val = bits % (UInt32) n;
}
while (bits - val + (n - 1) < 0);
return (int) val;
}
protected UInt32 Next(int bits)
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (UInt32)(seed >> (48 - bits));
}
private UInt64 seed;
}
Example:
Random rnd = new Random(42);
Console.WriteLine(rnd.NextInt(10));
Console.WriteLine(rnd.NextInt(20));
Console.WriteLine(rnd.NextInt(30));
Console.WriteLine(rnd.NextInt(40));
Console.WriteLine(rnd.NextInt(50));
Output on both platforms is 0, 3, 18, 4, 20.
If you have the source code of the java.util.Random class for your Java implementation, you can easily port it to .NET.
If you require both applications (Java and .NET) to use a certain random number generator, you'd better implement one in both platforms and use it instead, as the system provided version might change its behavior as a result of an update.(Looks like the Java specification precisely describes the behavior of its PRNG.)
If you don't need a cryptographically secure pseudorandom number generator then I would go for the Mersenne twister. You can find source code for C# here and Java here.
Well, you can look in the source code for Random.java and copy the algorithm, constants, etc.etc, but Random uses System.nanoTime in its constructor so you won't get the same results.
From java.util.Random
public Random() {
this(++seedUniquifier +
System.nanoTime()); }
I wouldn't be at all surprised if the source in C# would show you something similar.
Edit: Disregard, as has been pointed out, the constructor that takes an input seed never accesses time.
Maybe it would make sense to implement your own simple pseudo-random number generator? That way you have complete control and can garauntee the same seed gives the same results in both environments. Probably a bit more work than porting one to the other though.
Another option might be to write your random numbers out to a file once from one platform and then just load your random numbers for both platforms from that file, or you could load them from a service such as random.org

Why does it appear that my random number generator isn't random in C#?

I'm working in Microsoft Visual C# 2008 Express.
I found this snippet of code:
public static int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
the problem is that I've run it more than 100 times, and it's ALWAYS giving me the same answer when my min = 0 and max = 1. I get 0 every single time. (I created a test function to run it - really - I'm getting 0 each time). I'm having a hard time believing that's a coincidence... is there something else I can do to examine or test this? (I did re-run the test with min = 0 and max = 10 and the first 50ish times, the result was always "5", the 2nd 50ish times, the result was always "9".
?? I need something a little more consistently random...
-Adeena
The problem with min = 0 and max = 1 is that min is inclusive and max is exclusive. So the only possible value for that combination is 0.
random = new Random();
This initiates random number generator with current time (in sec). When you call your function many times before system clock changed, the random number generator is initiated with the same value so it returns same sequence of values.
Don't create a wrapper method for Next. It wastes cycles creating a new instance of the Random class. Just use the same one!
Random myRand = new Random();
for(int i = 0; i < 10; i++)
{
Console.WriteLine(myRand.Next(0, 10).ToString());
}
That should give you ten random values.
As has been said--Random is pseudo-random (as all implementations are), and if you create 100 instances with the same seed, you'll get 100 instances of the same results. Make sure that you're reusing the class.
Also, as folks have said, beware that MinValue is inclusive and MaxValue is exclusive. For what you want, do myRand.Next(0, 2).
That overload of Next() returns:
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not MaxValue. If minValue equals maxValue, minValue is returned.
0 is the only possible value for it to return. Perhaps you want random.NextDouble(), which will return a double between 0 and 1.
The min is inclusive, but the max is exclusive. Check out the API
You're always getting 0 because Random.Next returns integers. You need to call Random.NextDouble, which will return a number between 0 and 1. Also, you should reuse your Random instance, like this:
[ThreadStatic]
static Random random;
public static Random Random {
get {
if (random == null) random = new Random();
return random;
}
}
public static int RandomInteger(int min, int max)
{
return Random.Next(min, max);
}
public static double RandomDouble() //Between 0 and 1
{
return Random.NextDouble();
}
If you want cryptographically secure random numbers, use the RNGCryptoServiceProvider class; see this article
EDIT: Thread safety
Besides the 0-1 issue already noted in other answers, your problem is a real one when you're looking for a 0-10 range and get identical results 50 times in a row.
new Random() is supposed to return a random number with a seed initialized from the timer (current second), but apparently you're calling this code 50 times a second. MSDN suggests: "To improve performance, create one Random to generate many random numbers over time, instead of repeatedly creating a new Random to generate one random number.". If you create your random generator once outside the method, that should fix your "non-randomness" problem as well as improving performance.
Also consider this post for a better pseudo-random number generator than the system-supplied one, if you need "higher quality" pseudo-random numbers.
As others have mentioned, the Random being built multiple times per second uses the same second as the seed, so I'd put the Random constructor outside your loop, and pass it as a parameter, like this:
public static int RandomNumber(Random random, int min, int max)
{
return random.Next(min, max);
}
Also as mentioned by others, the max is exclusive, so if you want a 0 or 1, you should use [0,2] as your [min,max], or some larger max and then do a binary AND with 1.
public static int RandomOneOrZero(Random random)
{
return random.Next(0, int.MaxValue) & 1;
}
This is an addendum to any answers, as the answer to this specific question is the bounds should be (0, 2) not (0, 1).
However, if you want to use a static wrapper method, then you must remember that Random is not thread-safe, so you either need to provide your own synchronization mechanism or provide a per-thread instance. Here is a largely non-blocking implementation which uses one generator to seed each per-thread generator:
public static class ThreadSafeRandom
{
private static readonly Random seed = new Random();
[ThreadStatic]
private static Random random;
public static int Next(int min, int max)
{
if (random == null)
{
lock (seed)
{
random = new Random(seed.Next());
}
}
return random.Next(min, max);
}
// etc. for other members
}
You're misunderstanding the line "random.Next(min, max)". "min" is in the place of the lowest number allowed to be generated randomly. While "max" is in the place of the lowest number NOT allowed to be generated it is not in the place of the largest number allowed to be drawn. So when the line is random.Next(0, 1) you are basically only allowing 0 to be drawn.
Several posters have stated that Random() uses a seed based on the current second on the system clock and any other instance of Random created in the same second will have the same seed. This is incorrect. The seed for the parameterless constructor of Random is based on the tick count, or number of milliseconds since boot time. This value is updated on most systems approximately every 15 milliseconds but it can vary depending on hardware and system settings.
I found a very simple, but effective way to generate random numbers by just taking the last two digits of the current datetime milliseconds:
int seed = Convert.ToInt32(DateTime.Now.Millisecond.ToString().Substring(1, 2));
int cnr = new Random(seed).Next(100);
It is crude, but it works! :-)
Of course it would statistically generate the same number every hundred times. Alternatively, you could take all three digits or concatenate with other datetime values like seconds or so.
Your range is not correct. The minValue is inclusive in the range and the maxValue is exclusive in the range(meaning it won't be included in the range). So that's why it returns only 0.
Another useful note: having a Random instance be created in the method is not ideal as it might get the same seed on calling. So instead i would say use:
static Random gen = new Random();
public static int RandomNumber(int minValue, int maxValue){
return gen.Next(minValue, maxValue);
}
in VB i always start with the Randomize() function. Just call Randomize() then run your random function. I also do the following:
Function RandomInt(ByVal lower As Integer, ByVal upper As Integer) As Integer
Return CInt(Int((upper - lower + 1) * Rnd() + lower))
End Function
Hope this helps! :)

How do you generate a random number in C#?

I would like to generate a random floating point number between 2 values. What is the best way to do this in C#?
The only thing I'd add to Eric's response is an explanation; I feel that knowledge of why code works is better than knowing what code works.
The explanation is this: let's say you want a number between 2.5 and 4.5. The range is 2.0 (4.5 - 2.5). NextDouble only returns a number between 0 and 1.0, but if you multiply this by the range you will get a number between 0 and range.
So, this would give us random doubles between 0.0 and 2.0:
rng.NextDouble() * 2.0
But, we want them between 2.5 and 4.5! How do we do this? Add the smallest number, 2.5:
2.5 + rng.NextDouble() * 2.0
Now, we get a number between 0.0 and 2.0; if you add 2.5 to each of these values we see that the range is now between 2.5 and 4.5.
At first I thought that it mattered if b > a or a > b, but if you work it out both ways you'll find it works out identically so long as you don't mess up the order of the variables used. I like to express it with longer variable names so I don't get mixed up:
double NextDouble(Random rng, double min, double max)
{
return min + (rng.NextDouble() * (max - min));
}
System.Random r = new System.Random();
double rnd( double a, double b )
{
return a + r.NextDouble()*(b-a);
}
// generate a random number starting with 5 and less than 15
Random r = new Random();
int num = r.Next(5, 15);
For doubles you can replace Next with NextDouble
Here is a snippet of how to get Cryographically safe random numbers:
This will fill in the 8 bytes with a crytographically strong sequence of random values.
byte[] salt = new byte[8];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(salt);
For more details see How Random is your Random??" (inspired by a CodingHorror article on deck shuffling)
How random? If you can deal with pseudo-random then simply:
Random randNum = new Random();
randNum. NextDouble(Min, Max);
If you want a "better" random number, then you probably should look at the Mersenne Twister algorithm. Plenty of people hav already implemented it for you though
For an explaination of why Longhorn has been downmodded so much: http://msdn.microsoft.com/en-us/magazine/cc163367.aspx Look for the implementation of NextDouble and the explanation of what is a random double.
That link is also a goo example of how to use cryptographic random numbers (like Sameer mentioned) only with actual useful outputs instead of a bit stream.

Categories

Resources