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.)
Related
It's my generating algorithm it's generating random double elements for the array which sum must be 1
public static double [] GenerateWithSumOfElementsIsOne(int elements)
{
double sum = 1;
double [] arr = new double [elements];
for (int i = 0; i < elements - 1; i++)
{
arr[i] = RandomHelper.GetRandomNumber(0, sum);
sum -= arr[i];
}
arr[elements - 1] = sum;
return arr;
}
And the method helper
public static double GetRandomNumber(double minimum, double maximum)
{
Random random = new Random();
return random.NextDouble() * (maximum - minimum) + minimum;
}
My test cases are:
[Test]
[TestCase(7)]
[TestCase(5)]
[TestCase(4)]
[TestCase(8)]
[TestCase(10)]
[TestCase(50)]
public void GenerateWithSumOfElementsIsOne(int num)
{
Assert.AreEqual(1, RandomArray.GenerateWithSumOfElementsIsOne(num).Sum());
}
And the thing is - when I'm testing it returns every time different value like this cases :
Expected: 1
But was: 0.99999999999999967d
Expected: 1
But was: 0.99999999999999989d
But in the next test, it passes sometimes all of them, sometimes not.
I know that troubles with rounding and ask for some help, dear experts :)
https://en.wikipedia.org/wiki/Floating-point_arithmetic
In computing, floating-point arithmetic is arithmetic using formulaic
representation of real numbers as an approximation so as to support a
trade-off between range and precision. For this reason, floating-point
computation is often found in systems which include very small and
very large real numbers, which require fast processing times. A number
is, in general, represented approximately to a fixed number of
significant digits (the significand) and scaled using an exponent in
some fixed base; the base for the scaling is normally two, ten, or
sixteen.
In short, this is what floats do, they dont hold every single value and do approximate. If you would like more precision try using a Decimal instead, or adding tolerance by an epsilon (an upper bound on the relative error due to rounding in floating point arithmetic)
var ratio = a / b;
var diff = Math.Abs(ratio - 1);
return diff <= epsilon;
Round up errors are frequent in case of floating point types (like Single and Double), e.g. let's compute an easy sum:
// 0.1 + 0.1 + ... + 0.1 = ? (100 times). Is it 0.1 * 100 == 10? No!
Console.WriteLine((Enumerable.Range(1, 100).Sum(i => 0.1)).ToString("R"));
Outcome:
9.99999999999998
That's why when comparing floatinfg point values with == or != add tolerance:
// We have at least 8 correct digits
// i.e. the asbolute value of the (round up) error is less than tolerance
Assert.IsTrue(Math.Abs(RandomArray.GenerateWithSumOfElementsIsOne(num).Sum() - 1.0) < 1e-8);
I am developing a gaming platform that is subject to heavy regulatory scrutiny. I chose Math.NET because it seemed like a good fit. However I have just received this comment back from our auditors.
Comments please if this is accurate and how it can be resolved?
In RandomSource(), Next(int, int) is defined as follows:
public override sealed int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentException(Resources.ArgumentMinValueGreaterThanMaxValue);
}
if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
}
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
This creates a bias in the same way as before. Using an un-scaled value from the RNG and multiplying it by the range without previously eliminating the bias (unless the range is a power of 2, there will be a bias ).
Update: The implementation of Next(minInclusive, maxExclusive) has been changed in Math.NET Numerics v3.13 following this discussion. Since v3.13 it is no longer involving floating point numbers, but instead samples integers with as many bits as needed to support the requested range (power of two) and rejects those outside of the actual range. This way it avoids adding any bias on top of the byte sampling itself (as provided e.g. by the crypto RNG)
Assumption: DoSample() returns a uniformly distributed sample in the range [0,1) (double precision floating point number).
Multiplying it with the range R=max-min will result in a uniformly distributed sample in the range [0,R). Casting this to an integer, which is essentially a floor, will result in a uniformly distributed discrete sample of one of 0,1,2,...,R-1. I don't see where the fact that R is even, odd, or a power of two may affect bias in this step.
A few runs to compute 100'000'000 samples also do not indicate obvious bias, but of course this is no proof:
var r = new CryptoRandomSource();
long[] h = new long[8];
for (int i = 0; i < 100000000; i++)
{
h[r.Next(2,7)]++;
}
0
0
19996313
20001286
19998092
19998328
20005981
0
0
0
20000288
20002035
20006269
19994927
19996481
0
0
0
19998296
19997777
20001463
20002759
19999705
0
I've come up with this solution for a value between 0 and max inclusive. I'm no maths expert so comments welcome.
It seems to satisfy the regulatory spec I have which says
2b) If a particular random number selected is outside the range of equal distribution of re-scaling values, it is permissible to discard that random number and select the next in sequence for the purpose of re-scaling."
private readonly CryptoRandomSource _random = new CryptoRandomSource();
private int GetRandomNumber(int max)
{
int number;
var nextPowerOfTwo = (int)Math.Pow(2, Math.Ceiling(Math.Log(max) / Math.Log(2)));
do
{
// Note: 2nd param of Next is an *exclusive* value. Add 1 to satisfy this
number = _random.Next(0, nextPowerOfTwo + 1);
} while (number > max);
return number;
}
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!
Note: For brevity's sake, the following will not discern between randomness and pseudo-randomness. Also, in this context, constrained means between given min and max values)
The System.Random class provides random generation of integers, doubles and byte arrays.
Using Random.Next, one can easily generate random constrained values of type Boolean, Char, (S)Byte, (U)Int16, (U)Int32. Using Random.NextDouble(), one can similarly generate constrained values of types Double and Single (as far as my understanding of this type goes). Random string generation (of a given length and alphabet) has also been tackled before.
Consider the remaining primitive data types (excluding Object): Decimal and (U)Int64. Their random generation has been tackled as well (Decimal, (U)Int64 using Random.NextBytes()), but not when constrained. Rejection sampling (i.e. looping until the generated value is the desired range) could theoretically be used, but it is obviously not a practical solution. Normalizing NextDouble() won't work because it doesn't have enough significant digits.
In short, I am asking for the proper implementation of the following functions:
long NextLong(long min, long max)
long NextDecimal(decimal min, decimal max)
Note that, since System.DateTime is based on a ulong, the first function would allow for random constrained generation of such structs as well (similar to here, only in ticks instead of minutes).
This should do it. For decimal I utilized Jon Skeet's initial approach to generating random decimals (no constraints). For long I provided a method to produced random non-negative longs which is then used to create the a value in the random range.
Note that for decimal the resulting distribution is not a uniform distribution on [minValue, maxValue]. It merely is uniform on all the bit representations of decimals that fall in the range [minValue, maxValue]. I do not see an easy way around this without using rejection sampling.
For long the resulting distribution is uniform on [minValue, maxValue).
static class RandomExtensions {
static int NextInt32(this Random rg) {
unchecked {
int firstBits = rg.Next(0, 1 << 4) << 28;
int lastBits = rg.Next(0, 1 << 28);
return firstBits | lastBits;
}
}
public static decimal NextDecimal(this Random rg) {
bool sign = rg.Next(2) == 1;
return rg.NextDecimal(sign);
}
static decimal NextDecimal(this Random rg, bool sign) {
byte scale = (byte)rg.Next(29);
return new decimal(rg.NextInt32(),
rg.NextInt32(),
rg.NextInt32(),
sign,
scale);
}
static decimal NextNonNegativeDecimal(this Random rg) {
return rg.NextDecimal(false);
}
public static decimal NextDecimal(this Random rg, decimal maxValue) {
return (rg.NextNonNegativeDecimal() / Decimal.MaxValue) * maxValue; ;
}
public static decimal NextDecimal(this Random rg, decimal minValue, decimal maxValue) {
if (minValue >= maxValue) {
throw new InvalidOperationException();
}
decimal range = maxValue - minValue;
return rg.NextDecimal(range) + minValue;
}
static long NextNonNegativeLong(this Random rg) {
byte[] bytes = new byte[sizeof(long)];
rg.NextBytes(bytes);
// strip out the sign bit
bytes[7] = (byte)(bytes[7] & 0x7f);
return BitConverter.ToInt64(bytes, 0);
}
public static long NextLong(this Random rg, long maxValue) {
return (long)((rg.NextNonNegativeLong() / (double)Int64.MaxValue) * maxValue);
}
public static long NextLong(this Random rg, long minValue, long maxValue) {
if (minValue >= maxValue) {
throw new InvalidOperationException();
}
long range = maxValue - minValue;
return rg.NextLong(range) + minValue;
}
}
Let's assume you know how to generate N random bits. This is pretty easily done either using NextBytes or repeated calls to Random.Next with appropriate limits.
To generate a long/ulong in the right range, work out how large the range is, and how many bits it takes to represent it. You can then use rejection sampling which will at worst reject half the generated values (e.g. if you want a value in the range [0, 128], which means you'll generate [0, 255] multiple times). If you want a non-zero based range, just work out the size of the range, generate a random value in [0, size) and then add the base.
Generating a random decimal is signficantly harder, I believe - aside from anything else, you'd have to specify the distribution you wanted.
I came here looking for a way to generate 64 bit values within an arbitrary range. The other answers failed to produce a random number when given certain ranges (e.g. long.MinValue to long.MaxValue). Here's my version that seems to solve the problem:
public static long NextInt64(this Random random, long minValue, long maxValue)
{
Contract.Requires(random != null);
Contract.Requires(minValue <= maxValue);
Contract.Ensures(Contract.Result<long>() >= minValue &&
Contract.Result<long>() < maxValue);
return (long)(minValue + (random.NextUInt64() % ((decimal)maxValue - minValue)));
}
It uses the following extension Methods:
public static ulong NextUInt64(this Random random)
{
Contract.Requires(random != null);
return BitConverter.ToUInt64(random.NextBytes(8), 0);
}
public static byte[] NextBytes(this Random random, int byteCount)
{
Contract.Requires(random != null);
Contract.Requires(byteCount > 0);
Contract.Ensures(Contract.Result<byte[]>() != null &&
Contract.Result<byte[]>().Length == byteCount);
var buffer = new byte[byteCount];
random.NextBytes(buffer);
return buffer;
}
The distribution is not perfectly even when the size of the requested range is not a clean divisor of 2^64, but it at least provides a random number within the request range for any given range.
Based upon Jon Skeet's method, here's my stab at it:
public static long NextLong(this Random rnd, long min, long max)
{
if (max <= min)
{
throw new Exception("Min must be less than max.");
}
long dif = max - min;
var bytes = new byte[8];
rnd.NextBytes(bytes);
bytes[7] &= 0x7f; //strip sign bit
long posNum = BitConverter.ToInt64(bytes, 0);
while (posNum > dif)
{
posNum >>= 1;
}
return min + posNum;
}
Let me know if you see any errors.
long posNum = BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0);
use this instead of NextBytes
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! :)