The c#/XNA process for creating random numbers is pretty quick and easy, however, it is quite possibly the worst distributing random number generator I have ever seen. Is there a better method that is easy to implement for c#/XNA?
rand.Next() just doesn't suit my needs.
from:
static private Random rand = new Random();
I randomly place objects, all over my program. sometimes 10, sometimes 200.
When calling for random objects (the x val and y val are both random on a 2d plane), they group. The generation code is clean and calls them good, iterated cleanly and pulls a new random number with each value. But they group, noticeably bad, which isn't very good with random numbers after all. I'm intermediate skill with c#, I crossed over from as3, which seemed to handle randomness better.
I am well-aware that they are pseudo random, but C# on a windows system, the grouping is grotesque.
Can you use System.Security.Cryptography.RandomNumberGenerator from XNA?
var rand = RandomNumberGenerator.Create();
byte[] bytes = new byte[4];
rand.GetBytes(bytes);
int next = BitConverter.ToInt32(bytes, 0);
To get a value within a min/max range:
static RandomNumberGenerator _rand = RandomNumberGenerator.Create();
static int RandomNext(int min, int max)
{
if (min > max) throw new ArgumentOutOfRangeException("min");
byte[] bytes = new byte[4];
_rand.GetBytes(bytes);
uint next = BitConverter.ToUInt32(bytes, 0);
int range = max - min;
return (int)((next % range) + min);
}
For my project I use simple XOR algorythm. I don't know how good it distributes numbers, but it is easy to implement:
http://www.codeproject.com/KB/cs/fastrandom.aspx
It may also depend on how you're using System.Random. As a general rule, it is not a good idea to create new instances of Random over and over, as Random objects created at about the same time will very likely be seeded with the same random number (by default, time is used as the seed.) Instead, create a single instance of Random and use just that instance throughout your program.
Unless the goal is security, which is probably not the case here, you will be better off just using System.Random.
Related
This is my code to generate random numbers using a seed as an argument:
double randomGenerator(long seed) {
Random generator = new Random(seed);
double num = generator.nextDouble() * (0.5);
return num;
}
Every time I give a seed and try to generate 100 numbers, they all are the same.
How can I fix this?
If you're giving the same seed, that's normal. That's an important feature allowing tests.
Check this to understand pseudo random generation and seeds:
Pseudorandom number generator
A pseudorandom number generator (PRNG), also known as a deterministic
random bit generator DRBG, is an algorithm for generating a sequence
of numbers that approximates the properties of random numbers. The
sequence is not truly random in that it is completely determined by
a relatively small set of initial values, called the PRNG's state,
which includes a truly random seed.
If you want to have different sequences (the usual case when not tuning or debugging the algorithm), you should call the zero argument constructor which uses the nanoTime to try to get a different seed every time. This Random instance should of course be kept outside of your method.
Your code should probably be like this:
private Random generator = new Random();
double randomGenerator() {
return generator.nextDouble()*0.5;
}
The easy way is to use:
Random rand = new Random(System.currentTimeMillis());
This is the best way to generate Random numbers.
You shouldn't be creating a new Random in method scope. Make it a class member:
public class Foo {
private Random random
public Foo() {
this(System.currentTimeMillis());
}
public Foo(long seed) {
this.random = new Random(seed);
}
public synchronized double getNext() {
return generator.nextDouble();
}
}
This is only an example. I don't think wrapping Random this way adds any value. Put it in a class of yours that is using it.
That's the principle of a Pseudo-RNG. The numbers are not really random. They are generated using a deterministic algorithm, but depending on the seed, the sequence of generated numbers vary. Since you always use the same seed, you always get the same sequence.
Problem is that you seed the random generator again. Every time you seed it the initial state of the random number generator gets reset and the first random number you generate will be the first random number after the initial state
If you'd want to generate multiple numbers using one seed you can do something like this:
public double[] GenerateNumbers(long seed, int amount) {
double[] randomList = new double[amount];
for (int i=0;i<amount;i++) {
Random generator = new Random(seed);
randomList[i] = Math.abs((double) (generator.nextLong() % 0.001) * 10000);
seed--;
}
return randomList;
}
It will display the same list if you use the same seed.
Several of the examples here create a new Random instance, but this is unnecessary. There is also no reason to use synchronized as one solution does. Instead, take advantage of the methods on the ThreadLocalRandom class:
double randomGenerator() {
return ThreadLocalRandom.current().nextDouble(0.5);
}
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 6 years ago.
I have the following code inside a static method in a static class:
Random r = new Random();
int randomNumber = r.Next(1,100);
I have this inside a loop and I keep getting the same randomNumber!
Any suggestions here?
A good seed generation for me is:
Random rand = new Random(Guid.NewGuid().GetHashCode());
It is very random. The seed is always different because the seed is also random generated.
You should not create a new Random instance in a loop. Try something like:
var rnd = new Random();
for(int i = 0; i < 100; ++i)
Console.WriteLine(rnd.Next(1, 100));
The sequence of random numbers generated by a single Random instance is supposed to be uniformly distributed. By creating a new Random instance for every random number in quick successions, you are likely to seed them with identical values and have them generate identical random numbers. Of course, in this case, the generated sequence will be far from uniform distribution.
For the sake of completeness, if you really need to reseed a Random, you'll create a new instance of Random with the new seed:
rnd = new Random(newSeed);
Bit late, but the implementation used by System.Random is Environment.TickCount:
public Random()
: this(Environment.TickCount) {
}
This avoids having to cast DateTime.UtcNow.Ticks from a long, which is risky anyway as it doesn't represent ticks since system start, but "the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001, in the Gregorian calendar)".
Was looking for a good integer seed for the TestApi's StringFactory.GenerateRandomString
In case you can't for some reason use the same Random again and again, try initializing it with something that changes all the time, like the time itself.
new Random(new System.DateTime().Millisecond).Next();
Remember this is bad practice though.
EDIT: The default constructor already takes its seed from the clock, and probably better than we would. Quoting from MSDN:
Random() : Initializes a new instance of the Random class, using a time-dependent default seed value.
The code below is probably your best option:
new Random().Next();
public static Random rand = new Random(); // this happens once, and will be great at preventing duplicates
Note, this is not to be used for cryptographic purposes.
this workes for me:
private int GetaRandom()
{
Thread.Sleep(1);
return new Random(DateTime.Now.Millisecond).Next();
}
A good seed initialisation can be done like this
Random rnd = new Random((int)DateTime.Now.Ticks);
The ticks will be unique and the cast into a int with probably a loose of value will be OK.
I use this for most situations, keep the seed if there is a need to repeat the sequence
var seed = (int) DateTime.Now.Ticks;
var random = new Random(seed);
or
var random = new Random((int)DateTime.Now.Ticks);
Why do i need to create an instance of Random class, if i want to create a random number between 1 and 100 ....like
Random rand = new Random();
rand.Next(1,100);
Is there any static function of Random class to do the same? like...
Random.Next(1,100);
I don't want to create an instance unnecessarily
It is best practice to create a single instance of Random and use it throughout your program - otherwise the results may not be as random. This behavior is encouraged by not creating a static function.
You shouldn't worry about "creating an instance unnecessarily", the impact is negligible at best - this is the way the framework works.
//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
Copied directly from
It's not "unnecessary", because the Random class stores some state internally. It does that to make sure that if you call .Next() multiple times very quickly (in the same millisecond or tick or whatever) you still won't get the same number.
Of course, if that's not a problem in your case you can always combine those two lines of code into one:
new Random().Next(1, 100);
You already got answers here. Just reiterating the right solution:
namespace mySpace
{
public static class Util
{
private static Random rnd = new Random();
public static int GetRandom()
{
return rnd.Next();
}
}
}
So you can call:
var i = Util.GetRandom();
all throughout. If you strictly need a true stateless static method to generate random numbers, you can rely on a Guid.
public static class Util
{
public static int GetRandom()
{
return Guid.NewGuid().GetHashCode();
}
}
It's going to be a wee bit slower, but can be much more random than Random.Next, at least from my experience.
But not:
new Random(Guid.NewGuid().GetHashCode()).Next();
The unnecessary object creation is going to make it slower especially under a loop.
And never:
new Random().Next();
Not only its slower (inside a loop), it's randomness is... well not really good according to me..
From MSDN: Random Class (System):
"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. The following example illustrates that two Random objects that are instantiated in close succession generate an identical series of random numbers..."
Wikipedia explains PRNGs
The best way to do it is to have a ThreadStatic Random instance:
[ThreadStatic] static Random random;
Random Get() {
if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
return random;
}
This takes care of everything.
Thread safety
Performance
No need to seed
It eludes me why the .NET Framework (and any other framework on earth) does not use something in this spirit.
Creating a new instance of Random then calling it immediately multiple times, e.g.:
for (int i = 0; i < 1000; i++)
{
Random rand = new Random();
Console.WriteLine(rand.Next(1,100));
}
Will give you a distribution that is weighted towards the lower end of the range.
Doing it this way:
Random rand = new Random();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(rand.Next(1,100));
}
Will give you a better distribution.
Why not?
You need to create an instance because the way random numbers are generated is that previous answers affect subsequent answers. By default, the new Random() constructor uses the current system time to "seed" the sequence, but it doesn't have to: you can pass your own number in if you like. In particular:
var rand = new Random(1234);
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Will produce the same sequence of "random" number every time.
That means the Random class needs to keep instance data (the previous answer, or "seed") around for subsequent calls.
Creating a short-lived instance in C# is almost free. Don't waste your time worrying about this. You probably have better places to look for perf or memory gains.
Random number generators must maintain state in order to be "random." The random number generator creates a sequence that is generated based on a random seed. The problem is that nothing in a computer is actually random. The closest thing the computer has at hand is the system clock; that is the effectively the time at which the process takes place. So by default the current tick count of the system clock is used. If your application is fast enough then many random number calculations may occur under the same system tick. If the random number generator doesn't maintain state at all, it will provide the same random number multiple times (same input gives the same output). This is not usually what you want.
I know its already answered, but I just have to say that I prefer to use the singleton pattern in this case.
You need something similar to this if you want the syntax you mention.
namespace MyRandom
{
public class Random
{
private static m_rand = new Random();
public static Next(int min, int max)
{
return m_rand.Next(min, max);
}
}
}
This should allow you to do Random.Next(1,100); without having to worry about seeding.
I use this code to generate a random number.
Random R = new Random(0);
int Rand = R.Next(7);
but i get the same random number in each run of program.
Remove the 0 from the constructor and you'll get different random numbers.
If you pass a number to the constructor it's used as seed, by always specifying 0 you'll always get the same sequence.
You can specify an int32 which is random, but the easiest is to just not pass any parameter and you get a timebased seed
you have to change the seed of your random number generator object everytime you run your program, as what i've seen from you example, your current seed is 0, so you have to change it to something else if you want to get a different stream of random number... just a thought!
Seed your (pseudo)-random generator using a non-constant value, e.g. current time and date:
Random R = new Random(DateTime.Now.Ticks);
Read more about pseudo-random generators at Wikipedia.
Use time as initial seed of your PRNG.
You need to seed the random generator. You can use as follows:
Random R = new Random(DateTime.Now.Millisecond);
int Rand = R.Next(7);
Random number generators generate a new 'random' value based on the previous number generated. The seed is the initial value for this.
Seeding with the same value (like 0 in your example code) basically tells the random number generator to start with the same number each time. Having the exact same random number generated each time means your code becomes restartable. Example: Simulations use this to restart the simulation with changed parameters, but with the same 'data set'.
Another example:
I want to send myself a motivational message each day. Sometimes the messages are garbled. Being able to rerun the script, producing the same message again and again during a day, makes fixing this simple. In Perl code this means:
# By initialising the random generator with the day number since
# the epoch, we get the same quote during one day.
srand(time()/(24*3600));
my $i = int(rand(#messages));
If you want to produce different numbers each time, you will have to set this seed to something random. The options are many, like time, PID, delay between two keystrokes by the user, some value derived from the ethernet interface, etc. or more likely a combination of the above like time*PID.
Hope this clarifies the idea behind the concept of a random number seed value.
if we want a random number between 1 and 100 the code would look like this:
RandomNumberGenerator.GetRandomInt(1, 100)
The most secure way to generate random number is to use the System.Security.Cryptography.RandomNumberGenerator class.
Here is an example that will generate a number between 1 and 100;
public Number Rand()
{
byte[] Salt = new byte[8];
System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(Salt);
decimal result = 0;
foreach (byte b in Salt)
{
result = result * 255 + b;
}
while (result > 100)
{
result /= 10;
}
return result
}
Complete Code:
public static class RandomHelper
{
static object _myLock = new object();
static Random _random = new Random();
public static int RandomNumber(int min, int max)
{
lock (_myLock)
{
if (min == max)
return min;
if (min > max)
return _random.Next(max, min);
return _random.Next(min, max);
}
}
You need to seed the Random class with something more variable than 0. I normally use DataTime.Now.Ticks or you could use a new Guid's integer value.
Ok so I have a dice throw app...
When I step through the code it functions normally and 'results' contains the correct number of throw results and they appear to be random, when I leave the code to run and do exactly the same thing it produces a set of identical numbers.
I'm sure this is a logical error I cannot see but fiddling with it for hours hasnt improved the situation, so any help is much appriciated. :)
class Dice
{
public int[] Roll(int _throws, int _sides, int _count)
{
Random rnd = new Random();
int[] results = new int[_throws];
// for each set of dice to throw pass data to calculate method
for (int i = 0; i < _throws; i++)
{
int thisThrow = Calculate(_sides, _count);
//add each throw to a new index of array... repeat for every throw
results[i] = thisThrow;
}
return results;
}
private int Calculate(int _sides, int _count)
{
Random rnd = new Random();
int[] result = new int[_count];
int total = 0;
//for each dice to throw put data into result
for (int i = 0; i < _count; i++)
{
result[i] = rnd.Next(1, _sides);
}
//count the values in result
for (int x = 0; x < _count; x++)
{
total = total + result[x];
}
//return total of all dice to Roll method
return total;
}
}
First mistake: Never use multiple instances of Random, use a single instance, and pass that along with the other parameters.
When you create "Random rnd = new Random();" it is seeded by the current time. When you debug your code (which takes time) it will be seeded differently each time.
Create 1 instance of Random, and reference that everywhere.
You're creating a random class every time you need to create a number. Doing this will give you the nutty results.
See here: FROM MSDN
This problem can be avoided by creating a single Random object rather than multiple ones.
To improve performance, create one Random object to generate many random numbers over time, instead of repeatedly creating a new Random objects to generate one random number.
E.g. create a private instance of Random...
In addition to what has been mentioned before...
Use Random for things like dice, card games, choosing random images and so forth. If you ever need to create a random number for security sake, use System.Security.Cryptography.RandomNumberGenerator. This simple example shows creating a random integer.
RandomNumberGenerator gen = RandomNumberGenerator.Create();
byte[] myBytes = new byte[4];
gen.GetBytes(myBytes);
int myValue = (BitConverter.ToInt32(myBytes, 0));
DO NOT use this unless you have a security need. The performance is less than that of the Random class. I suppose you could use this to seed Random but that might be overkill.
EDIT: It occurred to me that I had never tested this. A quick performance test showed the following:
1,000,000 random numbers:
RandomNumberGenerator: 2.6 seconds
Random: .015 seconds.
So Random is about 150 times faster.
Give the constructor Random a seed. That's the problem.
http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx
Random r = new Random(DateTime.Now.Millisecond);