C# Random number hits far often than expected - c#

We have this random number generator:
Random rnd = new Random();
bool PiratePrincess = rnd.Next(1, 5000) == 1;
This is called on every page view. There should be a 1/5000 chance the variable is True. However, in ~15,000 page views this has been True about 20 times!
Can someone explain why this is the case, and how to prevent this so it is roughly 1/5000 times? It's not important at all for this to be truly random.
Edit: Should this do the trick?
Random rnd = new Random();
bool PiratePrincess = (rnd.Next() + ThisUser.UserID + ThisUser.LastVisit.Ticks + DateTime.Now.Ticks) % 5000 == 1;

How quickly are these pageviews coming in? new Random will initialize based on the current time, so many overlapping requests will get the same random seed. Randomize the seed based on the remote IP address hashed with the current time for more uniqueness.
That said, it is possible to flip a coin 20 times and get heads every single time. It's a legitimate random outcome.
Edit:this will do it
var r = new Random(
Convert.ToInt32(
(ThisUser.UserID ^ ThisUser.LastVisit.Ticks ^ DateTime.Now.Ticks) & 0xFFFFFFFF)
);
var isPiratePrincess = (r.Next (5000) == 42);

You only need instantiate a single instance of Random, thus:
public class Widget
{
private static rngInstance = new Random() ;
public bool IsPiratePrincess()
{
bool isTrue = rngInstance.Next(1, 5000) == 1 ;
return isTrue ;
}
}
Pseudo-random number generators implement a series. Each time you instantiate a new instance, it seeds itself based on (among other things) the current time-of-day and it starts a new series.
If you instantiate a new one on each invocation, and the instantiations are frequent enough, you'll likely see similarities in the stream of pseudo-random values generated, since the initial seed values are likely to be close to each other.
Edited to note: Since System.Random is not thread-safe, you probably want to wrap in such a way as to make it thread-safe. This class (from Getting Random Numbers in Thread-Safe Way) will do the trick. It uses a per-thread static field and instantiates a RNG instance for each thread:
public static class RandomGen2
{
private static Random _global = new Random();
[ThreadStatic]
private static Random _local;
public static int Next()
{
Random inst = _local;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_local = inst = new Random(seed);
}
return inst.Next();
}
}
I'm a little dubious about seeding each RNG instance with the output of another RNG. That strikes me a liable to bias the results. I think it might be better to use the default constructor.
Another approach would be to latch each access to a single RNG instance:
public static class RandomGen1
{
private static Random _inst = new Random();
public static int Next()
{
lock (_inst) return _inst.Next();
}
}
But that has some performance issues (bottleneck, plus overhead of a lock on each call).

You're creating a new random number generator with a new seed every time you're generating a number. The distribution of the values you get will have more to do with the seed than it does with the distribution characteristics of the algorithm being used.
I'm not sure what the best way is to achieve a more even distribution. If your traffic volume is low enough, you could use a hit counter on the page on check for divisibility by 5000, but that kind of approach would quickly run into contention problems if you tried to scale it.

If the problem is really the seed (as many people including myself suspect), you can either persist an instance of Random() (which will cause concurrency issues under high volume, but is fine for ~15,000 hits per day), or you can introduce more entropy to the seed.
If this were for an application where you do not want determined people to break the pseudo-random characteristics, you should look into software or hardware that generates a good seed on your server (poker websites often use a hardware entropy generator).
If you just want a good distribution and don't expect people to try to hack your solution, consider just blending various sources of entropy (the current timestamp, hash of the user's user agent string, the IPv4 address or hash of the IPv6 address, etc.).
UPDATE: You mention you have the user ID too. Hash that for entropy along with one or more of the items mentioned above, especially the ticks from the current timestamp.

You can get exactly 1/5000 if you avoid Random altogether.
vals = Enumerable.Repeat(false, 4999).ToList();
vals.Add(true);
// this or an in-memory shuffle if that is a concern
isPiratePrincess = vals.OrderBy(v => Guid.NewGuid()).ToList();
// remove values as it's queried & reset when empty.
The problem with using Random here is that you could be in a state where 20 in 15K were legitimately hit. In the next several thousand iterations, you'll hit a cold streak that regresses you towards the expected mean.

The random number generator uses the current time as a seed for the random number generator. So, if two come in at the same time, they could theoretically have the same seed. If you want your numbers to be unique with each other, you might want to use the same random number generator for all instances of the page.

Related

C# System.Random Next comes out sorted

I am trying to access random elements from an array, but the Random generator that I am using keeps on giving me numbers in order like so:
The numbers will always come out sequenced, never completely random (ie. the next number is always greater until the max is reached, then starts from low numbers again). This can be incremental or decremental as well.
I am using a seeded Random object and Random.Next(-100, 100).
This is not the same as the behaviour demonstrated on the MSDN Random.Next page
All I can think of is that the version of .Net packaged with Unity does not have the most recent Random? Any solutions to this confusion?
//Example
//Seed and ods set before the Awake method is called
public int seed;
public GameObject[] pathPartOds;
Random random;
GameObject[] path;
void Awake ()
{
random = new Random (seed);
}
void CreatePath (int length)
{
path = new GameObject[length];
for (int i = 0; i < length; i++)
path[i] = pathPartOds[random.Next (0, pathPartOds.length)];
}
Have used multiple seeds and they all give the same result, and I have been creating seeds using a random int
You need to create an instance of Random exactly once and pass that as a parameter into your function that draws a random number.
Else you'll ruin the generator's statistical properties due to it being seeded in a systematic (i.e. non-random) way. That explains the piecewise monotonicity of your output.

Random number behaves weird, not fully random

In my .NET game my rand function that are determining how much damage each out of the players five characters should take, however the 1st one always seems to be at the bottom of the scale and the last one at the top. So in my Character[0] the damage is rarely more than 1 more than the minimum rand value, and for each Character on higher index the damage taken is only randomized from higher up the scale.
public int GetDamage(int low, int high)
{
Random r = new Random();
int rand = r.Next(low, high);
return rand;
}
This is the randomizer I use. Then I update the health left like this:
int Damage = GetDamage(3, 10);
Characters[Target].Health = Characters[Target].Health - Damage;
In this example dmg is divided like this:
Number 1: 3-4
Number 2: 4-6
Number 3: 5-7
Number 4: 7-8
Number 5: 8-9
You have to reuse the same random instance otherwise you won't get really random values since it is created with the current time as seed. If you call GetDamage very fast(e.g. in a loop) you will get always the same values.
So either use a field/property in the class of GetDamage or pass the random instance to the method.
private Random _rnd = new Random();
public int GetDamage(int low, int high)
{
int rand = _rnd.Next(low, high);
return rand;
}
MSDN
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. This
problem can be avoided by creating a single Random object rather than
multiple ones.
You need to make your Random instance static, this seeds it once and thereafter you will get a more random looking number.
static Random r = new Random();
public int GetDamage(int low, int high)
{
int rand = r.Next(low, high);
return rand;
}
You need to seed the random number generator.
See: How do I seed a random class to avoid getting duplicate random values
Literally hundreds of this question on here, have a look around.

C# Random Numbers aren't being "random"

I know that the C# Random class does not make "true random" numbers, but I'm coming up with an issue with this code:
public void autoAttack(enemy theEnemy)
{
//Gets the random number
float damage = randomNumber((int)(strength * 1.5), (int)(strength * 2.5));
//Reduces the damage by the enemy's armor
damage *= (100 / (100 + theEnemy.armor));
//Tells the user how much damage they did
Console.WriteLine("You attack the enemy for {0} damage", (int)damage);
//Deals the actual damage
theEnemy.health -= (int)damage;
//Tells the user how much health the enemy has left
Console.WriteLine("The enemy has {0} health left", theEnemy.health);
}
I then call the function here (I called it 5 times for the sake of checking if the numbers were random):
if (thePlayer.input == "fight")
{
Console.WriteLine("you want to fight");
thePlayer.autoAttack(enemy1);
thePlayer.autoAttack(enemy1);
thePlayer.autoAttack(enemy1);
}
However, when I check the output, I get the exact same number for each 3 function calls. However, each time I run the program, I get a different number (which repeats 3 times) like this:
You attack the enemy for 30 damage.
The enemy has 70 health left.
You attack the enemy for 30 damage.
The enemy has 40 health left.
You attack the enemy for 30 damage.
The enemy has 10 health left.
I will then rebuild/debug/run the program again, and get a different number instead of 30, but it will repeat all 3 times.
My question is: how can I make sure to get a different random number each time I call this function? I am just getting the same "random" number over and over again.
Here is the random class call that I used:
private int randomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
My guess is that randomNumber creates a new instance of Random each time... which in turn creates a new pseudo-random number generator based on the current time... which doesn't change as often as you might think.
Don't do that. Use the same instance of Random repeatedly... but don't "fix" it by creating a static Random variable. That won't work well either in the long term, as Random isn't thread-safe. It will all look fine in testing, then you'll mysteriously get all zeroes back after you happen to get unlucky with concurrency :(
Fortunately it's not too hard to get something working using thread-locals, particularly if you're on .NET 4. You end up with a new instance of Random per thread.
I've written an article on this very topic which you may find useful, including this code:
using System;
using System.Threading;
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>
(() => new Random(Interlocked.Increment(ref seed)));
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}
If you change your new Random() call to RandomProvider.GetThreadRandom() that will probably do everything you need (again, assuming .NET 4). That doesn't address testability, but one step at a time...
You didn't show us the code for randomNumber. If it looks anything like
private int randomNumber(int m, int n) {
Random rg = new Random();
int y = rg.Next();
int z = // some calculations using m and n
return z;
}
Well, then there is your issue. If you keep creating new instances of Random, it's possible that they will sometimes have the same seed (the default seed is the system clock which has limited precision; create them quickly enough and they get the same seed) and then the sequence produced by this generator will always be the same.
To fix this, you have to instantiate an instance of Random once:
private readonly Random rg = new Random();
private int randomNumber(int m, int n) {
int y = this.rg.Next();
int z = // some calculations using m and n
return z;
}
And to clear up another point, even if you do this, the output from Random is still not "true" random. It's only psuedorandom.
What is randomNumber?
Typically a pseudo-random number generator is seeded (with a time-related thing, or something random like a time between two keypresses or network packets or something).
You don't indicate what generator you are using, nor how it is seeded.
Instantiate the object random outside the method.
( Random random = new Random(); should be written before the method)
It is also vital that you understand that random isn't really random.
if you generate random numbers in loop it will probably wont be random. because random numbers are basically created internally on current system time.
So place this code in the loop:
Thread.Sleep(10);
So the system will go to sleep for 10 m sec. And you will get new fresh random number.
Its a guaranteed solution. But this will also effect to performance of the system.

How do I use random numbers in C#?

I'm working on Pong in C# w/ XNA.
I want to use a random number (within a range) to determine things such as whether or not the ball rebounds straight, or at an angle, and how fast the ball moves when it hits a paddle.
I want to know how to implement it.
Use the Random class. For example:
Random r = new Random();
int nextValue = r.Next(0, 100); // Returns a random number from 0-99
Unless you need cryptographically secure numbers, Random should be fine for you... but there are two gotchas to be aware of:
You shouldn't create a new instance every time you need one. If you create an instance without specifying a seed, it will use the current time as the seed - which means if you create several instances in quick succession, many of them will produce the same sequence of numbers. Typically you create a long-lasting instance of Random and reuse it.
It's not thread-safe. If you need to generate random numbers from multiple threads, you should think about having one instance per thread. Read this blog post for more information - but make sure you read the comments as well, as they have very useful information.
Random rnd = new Random();
rnd.Next(minValue, maxValue);
i.e.
rnd.Next(1,10);
Use the Random object's Next method that takes a min and max and returns a value in that range:
var random = new Random();
int randomNum = random.Next(min, max);
While you can use the Random class like all the other are suggesting, the Random class only uses psuedo-random number generation. The RandomNumberGenerator, which can be found in the System.Security.Cryptography namespace, creates actual random numbers.
How To Use:
RandomNumberGenerator rng = RandomNumberGenerator.Create();
byte[] rand = new byte[25]; //Set the length of this array to
// the number of random numbers you want
rng.GetBytes(rand);
More Info: http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator(v=VS.80).aspx
Here is my random generator
private static Random rnd = new Random(Environment.TickCount);
private int RandomNum(int Lower, int Upper)
{
return rnd.Next(Lower, Upper);//MyRandomNumber;
}

Array 2 method random generated number

For a part of a program i need the following 2 methods.
The first method listed will generated a random number.
where the 2nd method will "call" this method to fill the array.
The array has a max. number of elements defefined on 100 (and all the random generated numbers should be between 1-100).
The problem is i never get random numbers generated. (either i get 100 x the same value, 3 random numbers divided over the 100 max. elements of the array, or the same value 100 times all over again).
The problem should be in the first method, but i cannot seem to figure out the problem.
Been staring at this for quite some time now...
The problem should be with the return, cause it DOES create random generated numbers. But how do i return the generated value every time? (the int method has to be called with the 3 parameters).
private int ValidNumber(int[] T, int X, int Range)
{
for (byte I = 0; I < T.Lenght; I++)
{
Random RndInt = new Random();
X = RndInt.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range);
}
}/*FillArray*/
Console code:
public void ExecuteProgram()
{
ClsBereken Ber = new ClsBereken();
//const byte Range = 100;
const int Max = 100;
int[] T = new int[Max];
Ber.FillArray(T, Max);
DisplayArray(T);
}/*ExecuteProgram*/
private void DisplayArray(int[] T)
{
for (byte i = 0; i < T.Length; i++)
{
Console.Write("{0,4} ", T[i]);
}
Console.WriteLine();
}/*DisplayArray*/
Any help alot appreciated.
Kind Regards.
Re-use the Random instance. NOTE I've edited this to show passing the Random instance down, but I'm really not sure what ValidNumber is trying to do - it looks like it is juts burning up CPU cycles? I would suggest you can remove ValidNumber completely (and just use the next value from the Random in FillArray), but presumably you are trying to do something here - I'm just not sure what!
private int ValidNumber(int[] T, int X, int Range, Random random)
{
for (byte I = 0; I < T.Lenght; I++)
{
X = random.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
Random random = new Random();
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range, random);
}
}/*FillArray*/
When you create a Random, it is "seeded" using the system clock, but this is rounded heavily. If you create lots of Random in a tight loop, they all get the same "seed", so they all create the same next number.
If necessary you could move the Random further out (if you have other loops), or make it static (but if you do that you need to worry about synchronization too).
The problem is that you are reinitializing rndint over and over.
take the line:
Random RndInt = new Random();
and move it in front of the loop and see if that fixes it.
When you initialize a random object, it is assigned a seed (probably based on the time), and that seed is used to generate a series of seemingly random values. However, if you plug in the same seed to two random objects, you will get the same series of random numbers.
So, what is happening in your code is you are initializing a new random object with a seed, and then asking for the first random number in its series. Then, you are initializing another random object (even though it is assigned to the same name, it is a new object) and it is getting the same seed, and you are again asking for the first random number in the series. So naturally, you are getting the same random number over and over.
You are continuously creating an new Random object. I'm afraid this is seeded (randomized) by the timestamp of creation. Since this is really fast and happens multiple times, the seed is the same, and so is the result of the call RndInt.Next(1, Range+1);.
By the way, even though not incorrect, it's not a common practice in c#.net to start with a capital letter on names of local variables and parameters.
Any random number generation algorithm* is not truly random; it is simply a deterministic algorithm that has been specifically designed to output numbers that resemble randomness. (See Pseudorandom number generator.) Since the algorithm is deterministic, its output is completely dependent upon a starting "seed" value.
The Random class in .NET has two constructors: one which takes an integer seed, and another which takes no parameters. This one bases its seed off the current time.
From this information perhaps you can guess why creating a new Random instance for every value in your array results in the entire array being filled with the same number: every time you construct a Random object within a very small time frame, it will have the same seed value, which means it will generate identical output to another Random object constructed within the same time frame.
As Marc Gravell has already indicated, you should be using only a single Random instance to generate a sequence of random numbers.
*Well, almost any. I believe there are hardware implementations of random number generators that factor in random noise (taken from the surrounding environment) and may therefore be considered "truly" random. Whether you believe these are actually random
depends on your personal definition of "random" and whether or not you believe that we live in a deterministic universe.
You can pass Random() a seed but if you send it the same seed number you will get the same results. The way you are using it
Random rnd = new Random();
Is using an auto-generated seed based on time. But you may not get seemingly random results if you don't at least sleep for a second. (Source http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx)
As everyone has mentioned here already your biggest issue is the fact you keep recreating the random object each iteration.

Categories