Add your own alternative version
Stats
179.1K views 2.3K downloads 60 bookmarked
Posted
30 Dec 2004

Comments and Discussions



I don't seem to be getting random values. Setting a seed and doing myRandom.Next(1000) gives me the same value after I reinitialize myRandom with a new seed.
Just taking the values from myRandom.Next() I can see that the values are not distributed over much range (and bigger seeds get bigger values of Next()) . I'm wondering if there is some other initialization step that I missed or if in fact this does not actually produce random values?





Testing against Random is like shooting fish in a barrel. Random is thread safe and has to update an atomic variable at each call. Fair benchmarking should be against an instance of ThreadLocalRandom, which is not thread safe.
Moreover, you can improve the speed by using 64bit shifts, which are as fast as 32bit shifts on modern CPUs. You can find some speed comparison here:
http://dsiutils.di.unimi.it/docs/it/unimi/dsi/util/XorShift64StarRandom.html
As you can see, beating ThreadLocalRandom is entirely another matter. The generator used in ThreadLocalRandom (congruential) is horrible, but it is very fast.





What are you talking about? .net does not have a ThreadLocalRandom class and the Random class is by no means thread safe msdn says the following:
The System.Random class and thread safety Instead of instantiating individual Random objects, we recommend that you create a single Random instance to generate all the random numbers needed by your app. However, Random objects are not thread safe. If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a threadsafe way, calls to methods that return random numbers return 0.





Shouldn't you also add a line to Reinitialise():
bitMask=1;
To make sure you are starting from the same place every time (if you are specifying seeds)?





Hi, yes you are correct. For now if you need to use this class I would recommend obtaining a more uptodate version with this and other fixes, available at:
http://sharpneat.svn.sourceforge.net/svnroot/sharpneat/trunk/SharpNeatV2/src/SharpNeatLib/Utility/FastRandom.cs
Thanks for the feedback,
Colin.





I saw a framerate improvement in my XNA game when I changed NextBytes to fill an array of uints (that I allocate in the constructor) and then copy this array to the output byte array using Buffer.BlockCopy.
I don't have specific performance metrics, but, intuitively, it makes sense that this should work.
public void NextBytes(byte[] buffer)
{
if (buffer.Length / 4 > mScratch.Length)
{
return;
}
uint x = this.x, y = this.y, z = this.z, w = this.w;
int i = (buffer.Length >> 2)  1;
uint t;
while ( i >= 0 )
{
t = (x ^ (x << 11));
x = y; y = z; z = w;
w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
mScratch[i] = w;
i;
}
Buffer.BlockCopy(mScratch, 0, buffer, 0, buffer.Length);
this.x = x; this.y = y; this.z = z; this.w = w;
}





One of greate problems of the original Random of System is the non existence of NextFloat (min,max) function.
How is possible implement a good function for this ?
Mauricio Cunha
www.mcunha98.cjb.net
mcunha98@terra.com.br





I wrote a simple benchmark in c# and to me it seems like System.Random is the fastest.
In 3 seconds FastRandom could do 4559590 iterations,
compared to System.Random with 4855556 iterations.
The numbers can variate a bit but in general the picture is the same. System.Random is fastest.
Note that I'm using .Net 3.5 libraries.
Benchmark code below.
using System;
public static class benchmark {
public static void RunAll(){
RunFastRandom();
RunRandom();
}
public static void RunRandom(){
Random randomNumber = new Random();
int num = 1;
int iterations = 0;
TimeSpan maxTime = new TimeSpan(0, 0, 3);
DateTime timer = DateTime.Now;
while(maxTime > (DateTime.Now  timer)){
num = randomNumber.Next();
iterations++;
}
Console.WriteLine("Iterations in " + maxTime + " seconds width System.Random: " + iterations);
}
public static void RunFastRandom(){
FastRandom randomNumber = new FastRandom();
int num = 1;
int iterations = 0;
TimeSpan maxTime = new TimeSpan(0, 0, 3);
DateTime timer = DateTime.Now;
while(maxTime > (DateTime.Now  timer)){
num = randomNumber.Next();
iterations++;
}
Console.WriteLine("Iterations in " + maxTime + " seconds width FastRandom: " + iterations);
}
}





Hi, thanks for the feedback.
There are a couple of points I'd like to make to anyone taking this benchmark as definitive. Firstly you get very different result if you run benchmarks with the debugger attached, also running released(optimised) code can make a substantial difference with this type of code. Running released code without the debugger I got:
FastRandom  13,729,267 iterations
System.Random  13,082,906
With the debugegr attached they both came out slower and System.Random won. However, your benchmark code calls DateTime.Now once on each loop and it turns out that the majority of CPU time is spent inside that property. If I iterate a fixed number of loops and time how long they take I get:
For 10^9 loops:
FastRandom  3,140ms
System.Random  12,500ms
Which equates to iterations per/sec of:
FastRandom  318M
System.Random  80M
The speed variations observed in your benchmark code are essentially showing us how the two random number classes are interacting with DateTime.Now and surrounding code, e.g. what code is left is CPU caches and registers etc. It's not an invalid test but I felt I need to qualify it here to any passing readers.
Out of interest I looked at System.Random in .Net Reflector and it looks liek the same code as in .Net 1.0 and 1.1.
Regards,
Colin.





I don't care for speed. I'll use your pseudorandom number generator for a platform independent project, because I need to generate a sequence of numbers for a given seed again and again. The implementations of System.Random in .NET and mono return different sequences for the same seed, so my application would not really do the same on every platform. Thanks for this nice alternative!
_____________________________________________________
This statement is false.





Hi Colin,
I've recently developed a managed library for random number generators and distributions and published it here[^] on CodeProject. I'd known your article (greate work by the way) for some time and decided to include a XorShift RNG. As you stated in a previous post that you're happy for your code to be reused, I took your FastRandom class as basis for my implementation which of course includes your summary and a reference to your article. When doing this, I've found a minor "error" and a performance improvement.
1.) The comment for the Next method states that "Values returned are over the range 0 to int.MaxValue1". But int.MaxValue (0x7FFFFFFF) can also occur (tested it) as your code generates a uint with full range and then does a bitwise AND with 0x7FFFFFFF. So int.MaxValue is returned when the unsigned integer 0xFFFFFFFF is generated.
If added a simple ifelse that returns the generated integer if its unequal int.MaxValue or generates a new one otherwise.
2.) In the NextBytes method it's possible to leave out the bitwise AND of w and e.g. 0x000000FF before casting to byte as the cast only involves the rightmost 8 bits and doesn't care for the rest.
buffer[i++] = (byte)( w&0x000000FF); > buffer[i++] = (byte)w;
buffer[i++] = (byte)((w&0x0000FF00) >> 8); > buffer[i++] = (byte)(w >> 8);
Best regards, Stefan
"Programming today is a race between software engineers striving to build bigger and better idiotproof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning."  Rick Cook www.troschuetz.de





Hi Stefan,
Thanks for the feedback and apologies for not responding sooner. Yeh sure no problem with reusing the code in your library. The librray looks very useful by the way. In the past when I've wanted to generate number sequences with different distributions I've had to resort to hacking/porting parts of randlib from C, which in turn was ported from Fortran I think and quite frankly that code is a mess!
With regard to point (1), I think the better solution would be simply to AND with 0x7FFFFFFE instead of 0x7FFFFFFF. My initial thought was that this would generate an uneven distribution of generated numbers, but of course each bit is random independently of all other bits so that masking out some bits still leaves an even distribution.
On point (2), thanks for this, I tried it and it is indeed functionally equivalent and also about 6% faster in the test I did.
I'm about to update the article and the file with these two changes, plus an update to the performance table as I noticed the figures are all out by a factor of 1000! Also the performance of System.Random and FastRandom under .Net 2.0 is very different than under .Net 1.1. FastRandom still wins though
Regards
Colin





Hello again!
colgreen wrote: apologies for not responding sooner
No problem I'm very patient
colgreen wrote: I think the better solution would be simply to AND with 0x7FFFFFFE instead of 0x7FFFFFFF
I thought about this one too, but it has a major drawback: the rightmost bit will always be zero and therefor only even numbers will be generated. Although they may be evenly distributed, I think this isn't very practical and favor using the ifelseapproach.
Best Regards, Stefan
"Programming today is a race between software engineers striving to build bigger and better idiotproof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning."  Rick Cook www.troschuetz.de





i needed a fast source for random bytes for filling files ans drives with random bytes. therefore i tried to optimize your code a bit. i measured the performance after each step multiple times with realtime priority. i noticed that reversing the loop (from length  1 to 0) increased throughput considerably. setting i to uint improved perf by 1%. i unrolled the loop 4 times to allow for outoforderexecution and to reduce the impact of the loop code. faster code was generated, when i used uintptr[i] instead of *uintptr++.
public unsafe void GetBytes(byte* buffer, int length)
{
uint x = this.x, y = this.y, z = this.z, w = this.w;
uint t;
uint* uintptr = (uint*)buffer;
length /= 4;
for (uint i = (uint)(length  4); ; i = 4)
{
t = x ^ (x << 11);
x = y; y = z; z = w;
w ^= t ^ (w >> 19) ^ (t >> 8);
uintptr[i] = w;
t = x ^ (x << 11);
x = y; y = z; z = w;
w ^= t ^ (w >> 19) ^ (t >> 8);
uintptr[i + 1] = w;
t = x ^ (x << 11);
x = y; y = z; z = w;
w ^= t ^ (w >> 19) ^ (t >> 8);
uintptr[i + 2] = w;
t = x ^ (x << 11);
x = y; y = z; z = w;
w ^= t ^ (w >> 19) ^ (t >> 8);
uintptr[i + 3] = w;
if (i == 0) { break; }
}
this.x = x; this.y = y; this.z = z; this.w = w;
}





We are developing an open source crossplatform product on Mono and DotNET. We are in need of a portable Random Number generator like the one published here (http://www.codeproject.com/csharp/fastrandom.asp). What legal licenses, if any, are placed on this code?
jnorman





Hi jnorman,
I suppose the answer is that there isn't one (a license), apart from whatever I agreed to when I posted the article. However, I'm happy for the code to be reused in whatever context so if you want I can send a modified version of the source with extra license blurb and get them to update the zip file on here.
Right now I'm thinking of switching over my other project (sharpneat) to a license less strict and more legally digestable than the L(GPL)  Something like the MIT or Apache licenses.
http://www.opensource.org/licenses/mitlicense.php
I take it that would be ok?
Colin.





(I tried emailing you in addition to this comment, sorry if you get this twice)
I still don't see a license mentioned. Any chance you could choose one?
Great work and thanks!
Dan





Reinitializing with the same seed should produce the same random sequence. Try this:
FastRandom r = new FastRandom();
r.Reinitialise(0);
int r1 = r.Next();
int r2 = r.Next();
r.Reinitialise(0);
int r3 = r.Next();
r1 and r3 should be the same number. I think you need to add this to the Reinitialise function:
y = 842502087;
z = 3579807591;
w = 273326509;
Thanks for the great article,
Jeremy





Ahh yes, silly mistake. Thanks for the feedback, I've submitted an updated zip file with this fix.
Colin





Nice article!
I wrote an additional routine, NextBytesUnsafe , that does NextBytes but with pointer arithmetic, and copies the w, x, y and z fields to local variables to speed it up even more.
Since w is already a random uint 4 bytes long, the routine copies the whole thing, and increments the pointer 4 bytes at a time.
The two downsides are that it needs /unsafe, and that the input buffer size must be divisble by 4.
Here's the code:
public unsafe void NextBytesUnsafe(byte[] buffer)
{
if(buffer.Length % 4 != 0)
throw new ArgumentException("Buffer length must be divisible by 4", "buffer");
uint x = this.x, y = this.y, z = this.z, w = this.w;
uint t;
fixed(byte* pByte0 = buffer)
{
uint* pDWord = (uint*)pByte0;
for(int i = 0, len = buffer.Length/4; i < len; i++)
{
t=(x^(x<<11));
x=y; y=z; z=w;
*pDWord++ = w = (w^(w>>19))^(t^(t>>8));
}
}
this.x = x; this.y = y; this.z = z; this.w = w;
}
On my Pentium 4 2.4ghz HT machine, the original implementation takes 3.078 seconds to generate 1024 random bytes 1,000,000 times, while the unsafe implementation takes 1.406 seconds  about 2 times faster.






colgreen wrote:
Still a lot slower than the unsafe method but of benefit if you can't or dont want to use the unsafe method.
Sorry my bad, didn't mean to confuse the local copies idea with using /unsafe
By the way, I'm writing a realtime cloud generator right now, and your article really saved the day for me.
Thanks again!





I know that there probably isn't, but is there an equivalent for this method (NextBytesUnsafe) for VB? If not, I'll just use C#. (And yes, I know VB doesn't have equivalents for pointers and that is why there probably isn't a VB equivalent for the code)





Nope, that's one of the very few things C# can do that VB can't.
You could compile the class in C# and add a reference to it from VB though... not sure how that'd affect performance but maybe it's worth a try.





To address a problem with seeding I have now recoded FastRandom to use a completely different algorithm, namely an xorshift method. Although there was a much simpler fix for the problem, I found this new algorithm a little faster so I decided to switch.
The algorithm itself is explained in a paper linked from the top of the article.





Thanks for the reference.
I have one remaining suggestion: inherit from System.Random and override methods as appropriate. This will truly make your class a direct replacement for System.Random .
Jeffrey
Everything should be as simple as possible, but not simpler.  Albert Einstein
Numerical components for C# and VB.NET





Perhaps I'll leave that as an exercise for the reader to do if and when they need a direct replacement e.g. if some binary library method only accepts System.Random objects.
Nonvirtual methods have eversoslightly more overhead than virtual ones, so the current arrangement gives the fastest possible speed.
Thanks for the ongoing feedback BTW. And I did spot the 'Marsaglia effect' in the link you posted





Hello
Why do you not use one of the standard algorithms that are proofed to behave randomly.
(I can't remember the name of THE standard algorithm that uses simple multiplication and modulo)
Nevertheless I think it's a good and efficient algorithm for random numbers
Aloha
Urs





Hi,
As I understand it the algorithm used is proven to be random and to have a long period. With regard to the short period of 1 problem, George Marsaglia stipulates some restrictions on the seeds values that should be used. However, I have now recoded the FastRandom class to use another of Marsaglias's algorithms that is even faster than multiplyandcarry. This new algorithm is based on XOR and bit shifting only and does not exhibit the same problem with the Reinitialise methods.
Just waiting for the Codeproject folks to update the article





Please define "proven to be random".
I would like to note some references on rngs:
D. E. Knuth's "The Art of Computer Programming" gives an extensive discussion on (mostly linear) random number generators.
Theory and Practice of Random Number Generation by Peter Hellekalek at the Mathematics Department of the University of Salzburg is a good starting point for practitioneers.
Jens

Jens Scheidtmann





Well ok. The algorithm is proven to provide a good pseudorandom sequence of long period. Please see George Marsaglia's paper (linked in the article) and general body of work on RNGs for more info on tests of randomness, and mathemetical basis of this RNG, etc.





Urs Enzler wrote:
Why do you not use one of the standard algorithms that are proofed to behave randomly. (I can't remember the name of THE standard algorithm that uses simple multiplication and modulo)
I believe you're talking about the Linear Congruential method. The algorithm in the original article used a combination of two such RNG's. Whatever method you use, you must be careful to verify that the sequence you generate works well using the parameters you chose. A bad choice of parameters can destroy the appearance of randomness.
'Standard' is not always better. The RANDU random number generator was published by IBM in the 60's and something of a standard back then. It is of the linear congruential type. However, it was later discovered that it wasn't all that good. See this page[^] for an illustration (Java applet).
Constructing pseudorandom number generators is a bit of an art, it seems. There is a whole range of algorithms out there, with a large range of speed and quality.
Which algorithm you use depends on your application. For example, cryptography requires much better randomness than a simple game because the whole point of cryptography is to destroy any appearance of a pattern or relationship between the encrypted data and the original. In simulations, a pattern like that produced by the RANDU algorithm can introduce a bias that taints the results.
Jeffrey
Everything should be as simple as possible, but not simpler.  Albert Einstein
Numerical components for C# and VB.NET





You are absolutely right. With 'standard' I meant an algorithm that is proven to be good.
The algorithm you mentioned is indeed very famous because a lot of scientific work had to be thrown away because of it On the other hand some simulation proofed to be very stable even against a very bad random number generator.





colgreen wrote:
That simulation requires that the RNG be reset with a given seed 1000s of times per second. FastRandom's Reinitialise() methods therefore provide a nice performance boost over System.Random in that case. I then discovered that a number of further performance improvements could be made to the Next*() methods.
How many random numbers do actually generate within the loop? Wouldn't it be a lot faster if you created the sequence outside the loop, put them in an array, and inside the loop just picked off numbers from that array?? You may be able to do some preprocessing of these random values outside the loop, leading to an even greater speedup.
Jeffrey
Everything should be as simple as possible, but not simpler.  Albert Einstein
Numerical components for C# and VB.NET





Hi, Yes that is an option but some simulations are open ended with regards to their end condition and so could require millions or billions of rnd numbers. But yes, for the more common requirement of say a few thousand numbers caching numbers would be faster, in fact I might try this out.
Thanks for the suggestion.
Colin





I can see why this routine is very fast, but this is an extremely basic mechanism for generating random numbers which can result in a very short period for particular values





Jabes wrote:
this is an extremely basic mechanism for generating random numbers which can result in a very short period for particular values
Indeed it can! The period can be as short as 1:
rng = new FastRandom(2006912572, 1179647999);
if (rng.Next() == rng.Next())
Console.WriteLine("'Random' sample is always the same.");
Now, it is indeed very fast, and for most seeds it will produce a pretty good sequence. This example shows that caution is always a good thing.
The creator of this random number generator is one George Marsaglia, who wrote this message[^] to the sci.stat.math newsgroup. He also offers replacements for the parameters 36969 and 18000. Marsaglia also wrote DIEHARD[^], a series of programs for testing the quality of random number generators.
Jeffrey
Everything should be as simple as possible, but not simpler.  Albert Einstein
Numerical components for C# and VB.NET





I think this problem can be addressed with some extra logic in the Reinitialise methods that ensure that bad seeds are avoided. Note that I already added conditions to avoid zero seeds, which will just result in a sequence of zero's. And as you rightly point out (Jabes) there are other seeds that also perform poorly  which is a problem I hadn't spotted, but the mechanism itself is capable of generating good sequences. That is, it isn't inherently flawed AFAIK.





If you are after an excellent random number generator, then the mersenne twister is excellent. I have used it in the past with very good, fast results.
I haven't seen a C# implementation yet, but I'm sure there must be one kicking around





There is one as part of the Netron project: http://netron.sourceforge.net/wp/[^]
The file would be C:\Program Files\The Netron Project\Cobalt\NetronGraphLibrary\Utils\Maths\MersenneTwister.cs
using System;
namespace Netron.GraphLib.Maths
{
/////////////////////////////////////////////////////////////////////////////
// C# Version Copyright (c) 2003 CenterSpace Software, LLC //
// //
// This code is free software under the Artistic license. //
// //
// CenterSpace Software //
// 2098 NW Myrtlewood Way //
// Corvallis, Oregon, 97330 //
// USA //
// http://www.centerspace.net //
/////////////////////////////////////////////////////////////////////////////
/*
A Cprogram for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997  2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp
*/
///
/// Class MersenneTwister generates random numbers from a uniform distribution using
/// the Mersenne Twister algorithm.
///
/// Caution: MT is for MonteCarlo, and is NOT SECURE for CRYPTOGRAPHY
/// as it is.
[Serializable()]public class MersenneTwister
{
#region Constants 
// Period parameters.
private const int N = 624;
private const int M = 397;
private const uint MATRIX_A = 0x9908b0dfU; // constant NetronVector a
private const uint UPPER_MASK = 0x80000000U; // most significant wr bits
private const uint LOWER_MASK = 0x7fffffffU; // least significant r bits
private const int MAX_RAND_INT = 0x7fffffff;
#endregion Constants
#region Instance Variables 
// mag01[x] = x * MATRIX_A for x=0,1
private uint[] mag01 = {0x0U, MATRIX_A};
// the array for the state NetronVector
private uint[] mt = new uint[N];
// mti==N+1 means mt[N] is not initialized
private int mti = N+1;
#endregion Instance Variables
#region Constructors 
///
/// Creates a random number generator using the time of day in milliseconds as
/// the seed.
///
public MersenneTwister()
{
init_genrand( (uint)DateTime.Now.Millisecond );
}
///
/// Creates a random number generator initialized with the given seed.
///
/// The seed.
public MersenneTwister( int seed )
{
init_genrand( (uint)seed );
}
///
/// Creates a random number generator initialized with the given array.
///
/// The array for initializing keys.
public MersenneTwister( int[] init )
{
uint[] initArray = new uint[init.Length];
for ( int i = 0; i < init.Length; ++i )
initArray[i] = (uint)init[i];
init_by_array( initArray, (uint)initArray.Length );
}
#endregion Constructors
#region Properties 
///
/// Gets the maximum random integer value. All random integers generated
/// by instances of this class are less than or equal to this value. This
/// value is 0x7fffffff (2,147,483,647).
///
public static int MaxRandomInt
{
get
{
return 0x7fffffff;
}
}
#endregion Properties
#region Member Functions 
///
/// Returns a random integer greater than or equal to zero and
/// less than or equal to MaxRandomInt.
///
/// The next random integer.
public int Next()
{
return genrand_int31();
}
///
/// Returns a positive random integer less than the specified maximum.
///
/// The maximum value. Must be greater than zero.
/// A positive random integer less than or equal to maxValue.
public int Next( int maxValue )
{
return Next( 0, maxValue );
}
///
/// Returns a random integer within the specified range.
///
/// The lower bound.
/// The upper bound.
/// A random integer greater than or equal to minValue, and less than
/// or equal to maxValue.
public int Next( int minValue, int maxValue )
{
if ( minValue > maxValue )
{
int tmp = maxValue;
maxValue = minValue;
minValue = tmp;
}
return (int)( Math.Floor((maxValueminValue+1)*genrand_real1() + minValue) );
}
///
/// Returns a random number between 0.0 and 1.0.
///
/// A singleprecision floating point number greater than or equal to 0.0,
/// and less than 1.0.
public float NextFloat()
{
return (float) genrand_real2();
}
///
/// Returns a random number greater than or equal to zero, and either strictly
/// less than one, or less than or equal to one, depending on the value of the
/// given boolean parameter.
///
///
/// If true, the random number returned will be
/// less than or equal to one; otherwise, the random number returned will
/// be strictly less than one.
///
///
/// If includeOne is true, this method returns a
/// singleprecision random number greater than or equal to zero, and less
/// than or equal to one. If includeOne is false, this method
/// returns a singleprecision random number greater than or equal to zero and
/// strictly less than one.
///
public float NextFloat( bool includeOne )
{
if ( includeOne )
{
return (float) genrand_real1();
}
return (float) genrand_real2();
}
///
/// Returns a random number greater than 0.0 and less than 1.0.
///
/// A random number greater than 0.0 and less than 1.0.
public float NextFloatPositive()
{
return (float) genrand_real3();
}
///
/// Returns a random number between 0.0 and 1.0.
///
/// A doubleprecision floating point number greater than or equal to 0.0,
/// and less than 1.0.
public double NextDouble()
{
return genrand_real2();
}
///
/// Returns a random number greater than or equal to zero, and either strictly
/// less than one, or less than or equal to one, depending on the value of the
/// given boolean parameter.
///
///
/// If true, the random number returned will be
/// less than or equal to one; otherwise, the random number returned will
/// be strictly less than one.
///
///
/// If includeOne is true, this method returns a
/// singleprecision random number greater than or equal to zero, and less
/// than or equal to one. If includeOne is false, this method
/// returns a singleprecision random number greater than or equal to zero and
/// strictly less than one.
///
public double NextDouble( bool includeOne )
{
if ( includeOne )
{
return genrand_real1();
}
return genrand_real2();
}
///
/// Returns a random number greater than 0.0 and less than 1.0.
///
/// A random number greater than 0.0 and less than 1.0.
public double NextDoublePositive()
{
return genrand_real3();
}
///
/// Generates a random number on [0,1) with 53bit resolution.
///
/// A random number on [0,1) with 53bit resolution
public double Next53BitRes()
{
return genrand_res53();
}
///
/// Reinitializes the random number generator using the time of day in
/// milliseconds as the seed.
///
public void Initialize()
{
init_genrand( (uint)DateTime.Now.Millisecond );
}
///
/// Reinitializes the random number generator with the given seed.
///
/// The seed.
public void Initialize( int seed )
{
init_genrand( (uint)seed );
}
///
/// Reinitializes the random number generator with the given array.
///
/// The array for initializing keys.
public void Initialize( int[] init )
{
uint[] initArray = new uint[init.Length];
for ( int i = 0; i < init.Length; ++i )
initArray[i] = (uint)init[i];
init_by_array( initArray, (uint)initArray.Length );
}
#region Methods ported from C 
// initializes mt[N] with a seed
private void init_genrand( uint s)
{
mt[0]= s & 0xffffffffU;
for (mti=1; mti> 30)) + mti);
// See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
// In the previous versions, MSBs of the seed affect
// only MSBs of the array mt[].
// 2002/01/09 modified by Makoto Matsumoto
mt[mti] &= 0xffffffffU;
// for >32 bit machines
}
}
// initialize by an array with arraylength
// init_key is the array for initializing keys
// key_length is its length
private void init_by_array(uint[] init_key, uint key_length)
{
int i, j, k;
init_genrand(19650218U);
i=1; j=0;
k = (int)(N>key_length ? N : key_length);
for (; k>0; k)
{
mt[i] = (uint)((uint)(mt[i] ^ ((mt[i1] ^ (mt[i1] >> 30)) * 1664525U)) + init_key[j] + j); /* non linear */
mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machines
i++; j++;
if (i>=N) { mt[0] = mt[N1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N1; k>0; k)
{
mt[i] = (uint)((uint)(mt[i] ^ ((mt[i1] ^ (mt[i1] >> 30)) * 1566083941U)) i); /* non linear */
mt[i] &= 0xffffffffU; // for WORDSIZE > 32 machines
i++;
if (i>=N) { mt[0] = mt[N1]; i=1; }
}
mt[0] = 0x80000000U; // MSB is 1; assuring nonzero initial array
}
// generates a random number on [0,0xffffffff]interval
uint genrand_int32()
{
uint y;
if (mti >= N)
{ /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489U); /* a default initial seed is used */
for (kk=0;kk> 1) ^ mag01[y & 0x1U];
}
for (;kk> 1) ^ mag01[y & 0x1U];
}
y = (mt[N1]&UPPER_MASK)(mt[0]&LOWER_MASK);
mt[N1] = mt[M1] ^ (y >> 1) ^ mag01[y & 0x1U];
mti = 0;
}
y = mt[mti++];
// Tempering
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680U;
y ^= (y << 15) & 0xefc60000U;
y ^= (y >> 18);
return y;
}
// generates a random number on [0,0x7fffffff]interval
private int genrand_int31()
{
return (int)(genrand_int32()>>1);
}
// generates a random number on [0,1]realinterval
double genrand_real1()
{
return genrand_int32()*(1.0/4294967295.0);
// divided by 2^321
}
// generates a random number on [0,1)realinterval
double genrand_real2()
{
return genrand_int32()*(1.0/4294967296.0);
// divided by 2^32
}
// generates a random number on (0,1)realinterval
double genrand_real3()
{
return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
// divided by 2^32
}
// generates a random number on [0,1) with 53bit resolution
double genrand_res53()
{
uint a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
// These real versions are due to Isaku Wada, 2002/01/09 added
#endregion Methods ported from C
#endregion Member Functions
}
}





Correct.
Worst ever random generator!
slightly better than:
public void nextBytes(byte[] buffer)
{
// Why bother ?
}
Passes FIPS 1401 with approximately 0.7 %.





I second your opinion Jabes.







General News Suggestion Question Bug Answer Joke Praise Rant Admin Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

