In HA! I use a C# implementation of the Mersenne Twister for RNG, but there is another option. After seeing John Lunsford's excellent Crypto presentation at the Columbia, SC .NET User Group, I decided to start playing with the RandomNumberGenerator class in the System.Security.Cryptography namespace.

I haven't done a comprehensive analysis on performance yet, but "they say" that the Mersenne Twister is faster and more random. Depending on your needs, the Mersenne Twister might still be the better way to go. However, both of these are so much better than System.Random, and the differences between them so negligible, that it might not matter. Depends on your needs, of course.

The Crypto stuff works like this:

Dim b(10) As Byte System.Security.Cryptography.RandomNumberGenerator.Create.GetNonZeroBytes(b)

That gives me an array of 10 numbers, each between 1 and 255. There is another method, called *GetBytes* that includes 0 in the results.

Of course, if you want a range OTHER than 1 - 255, you have to do a little extra work. Let's say you want numbers in the range of 1 - 20, all you do is MOD the resulting number by 20 and then add 1. The following code will take each value and adjust it down to the specified range:

For intCtr = 0 To 9 b(intCtr) = (b(intCtr) Mod 20) + 1 Next

Now you have an array of 10 numbers, each between 1 and 20. What you do with them at this point is largely up to you. If you need pseudo-random numbers larger than 255, then I think you're definitely better off using the Mersenne Twister. For simulating die rolls, such as 1-4, 1-6, 1-8, 1-10, 1-12, 1-20 or 1-100 this methods works great, is extremely simple to use and doesn't require the additional effort of adding something as complex as a Mersenne Twister to your code.

- Share This Post:
- Short Url: http://wblo.gs/Erd

## Feedback

All things considered, it seems like a pretty even distribution.

After all, if you are rolling a 20 sided die, you have a 5% chance of getting a 20 on each roll.

You have 256 possible values and you are trying to fit them into 20 buckets.

YOu don't have to do a big sample. Just put every number from 0...255 into your function (x mod 20) +1. The numbers 1-16 will be returned 13 times, but the numbers 17-20 only 12.

So the chance of getting a 1 (or 2-16) is 13/256 = 5.078125% and the chance of a 17 (or 18-20) is 12/256 = 4.6875%

The problem isn't the random number generator. Its that you only have 255 inputs into whtever formula you have and you have to share those 255 between your 20 output values so no matter how you do it you will HAVE to have 4 numbers that come back 12 times and 16 numbers that come back 13 times.

So how to fix it ? Back to the mersenne primes is one way. Or just use the bytes that come back as a long - get 4 bytes from 0 to 255 giveing you a much bigger range into your mod function. Yes there will still be a slight bias but it gets smaller the bigger range you have to start with.

mersenne twister c#

into google

(says andy carefully trying to avoid typing a URL!)

I just meant that alternatives are always good.

For m As Integer = 0 To 3

For n As Integer = 0 To 3

i = r.Next(1, 10)

textboxGrid(m, n).Text = i

Next n

Next m

i.e if getbytes returns 255, discard it and call it again, repeat until you get a number between 1 and 240.

Then you can use Mod and still have an even distribution.

var rndBytes = new byte[8];

RandomNumberGenerator.Create().GetBytes(rndBytes);

ulong uIntResult = BitConverter.ToUInt64(rndBytes, 0);

double doubleResult = (double)(uIntResult / (decimal)UInt64.MaxValue);

// get a value between min and max exlusive of max (like System.Random.Next(int minValue, int maxValue)

int intresult = (int)Math.Min(Math.Max(Math.Round(minValue + (NextDouble() * (maxValue-minValue)) - 0.5 , 0, MidpointRounding.AwayFromZero), minValue), maxValue);

int intresult = (int)Math.Min(Math.Max(Math.Round(minValue + (doubleResult * (maxValue-minValue)) - 0.5 , 0, MidpointRounding.AwayFromZero), minValue), maxValue);