Click here to Skip to main content
15,895,554 members
Articles / Programming Languages / C#
Article

A fast equivalent for System.Random

Rate me:
Please Sign up or sign in to vote.
4.88/5 (28 votes)
10 Oct 20067 min read 245.5K   3.4K   61   42
A simple and fast random number generator that can be substituted in place of System.Random, with extra methods and fast re-initialization.

Introduction

Here I present a class that can be substituted in place for the the .NET framework's System.Random class to provide some advantages:

  1. Based on a simple and fast XOR-shift pseudo random number generator (RNG) specified in the paper: Marsaglia, George. (2003). Xorshift RNGs). This particular implementation of XOR-shift has a period of 2^128-1. See the above paper to see how this can be easily extended if you need a longer period. At the time of writing, I could find no information on the period of System.Random for comparison.
  2. Faster than System.Random. Up to 8x faster, depending on which methods are called and which CLR is used (see table below).
  3. Direct replacement for System.Random. This class implements all of the methods that System.Random does plus some additional methods for generating random uints and booleans. The like named methods are functionally equivalent to those in System.Random.
  4. Allows fast re-initialization with a seed, unlike System.Random which accepts a seed at construction time only, which then executes a relatively expensive initialization routine. This provides a vast speed improvement if you need to reset the pseudo-random number sequence many times, e.g., if you want to re-generate the same sequence many times. An alternative might be to cache random numbers in an array, but that approach is limited by memory capacity and the fact that you may also want a large number of different sequences cached. Each sequence can be represented by a single seed value (int).

Background

I created FastRandom in order to achieve greater speed in a prey capture simulation within another project, SharpNEAT. 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. The first version of FastRandom posted on CodeProject used a multiply-with-carry (MWC) algorithm devised by George Marsaglia. Forum posters pointed out that some seeds generated a sequence of the same number, and whilst investigating the solution, I came across another of Marsaglia's algorithms utilizing an XOR-shift technique that was even faster than MWC. The current version of FastRandom therefore implements XOR-shift and should also provide good random sequences for all seed values (including 0).

The Math

The random number generator (RNG) used generates new numbers using just bitwise XOR and left and right shifts. The method NextUInt provides the simplest example because it returns the generated 32 bit number (uint) without any further manipulation:

C#
public uint NextUInt() 
{
   uint t= (x^(x<<11)); 
   x=y;
   y=z; 
   z=w;
   return (w= (w^(w>>19))^(t^(t>>8)));
}

The state of the RNG is described by the four uint variables x, y, z and w. w represents most recently generated number, and a history of the last four generated numbers is maintained with the inclusion of the x, y and z variables. New numbers are generated by applying various shifts and XORs to x, which represents the number generated four calls ago. Storing and using the history of the last four numbers in this manner results in an RNG with a longer period, here the period is 2^128-1. The period can be shortened or lengthened by adjusting the amount of history variables stored. For more information on this, see the paper referred to above.

All of the other Next*() methods are variations of this technique, taking the 32 bits generated and manipulating them into double, int, bytes, etc.

Reinitialise() methods

The Reinitialise methods allow the caller to reset FastRandom with a single integer seed value and thus generate the same set of random numbers over again. This can sometimes be useful, e.g., in simulations where you might want to recreate the same scenario exactly as before. Note that System.Random provides no such method for re-initializing (re-seeding) the class once it is constructed; the only option is to construct a new instance and pass the seed in to the constructor, which then executes code to build an array of seed data. By allowing re-initialization and avoiding the need to build a seed data array, FastRandom provides a significant performance improvement where reseeding is required.

Other Performance Improvements (in comparison to System.Random)

  • Avoid use of floating point arithmetic where possible. This applies to Next() and NextBytes(byte[]).
  • Where floating point arithmetic is used, ensure that casts are performed from int to double, and not from uint to double. In tests, casting from uint took twice as long as casting from int. This speed-up applies to NextDouble(), Next(int) and Next(int,int).
  • Don't declare methods as virtual. The virtual method table generates some overhead even in released, optimized code where the methods haven't actually been overridden. System.Random's methods are declared as virtual and therefore generate this overhead. There may be sound reasons for this within the .NET framework, but if you just want a fast RNG today, then we can omit the virtual keyword in our declarations.
  • In the NextBytes method, we generate 32 bits at a time and fill the byte array in 4 byte chunks.

Performance Comparison Table

For prior readers of this article please note that this is an updated version of the table that takes into account improvements made to FastRandom.cs made since the article was first posted and also to the .NET runtime engine between .NET 1.1 and .NET 2.0.

Other notes:

  • Both FastRandom and System.Random run faster on the .NET 2.0 CLR than on .NET 1.1. However, System.Random does benefit more than FastRandom and so the performance gap between the two classes is narrower in .NET 2.0.
  • One exception to the above point is Next(int,int) with a long range between the two integer parameters, on the .Net 1.1 CLR FastRandom's version actually ran slower, however on .NET 2.0 this result is now reversed as can be seen in the table below.

The following performance figures were obtained using released, optimized code executing on an Intel Core 2 Duo E660 overclocked to 3.11Ghz. This is a dual core chip, however these performance figures are for a single core only:

 

System.Random (millions calls/sec)

FastRandom (millions calls/sec)

Speed increase

Next()

103.252

220.750

2.14x
Next(int)

51.826

142.2472.14x
Next(int,int)

34.506

87.6802.54x
Next(int,int) <long range>*

16.182

30.2611.87x
NextDouble()

87.680

185.5282.12x
NextBytes() 1024 byte array in tests

0.105

0.9278.83x
NextUInt()

n/a

261.437n/a
NextInt()

n/a

256.081n/a
NextBool()

n/a

312.500n/a

* - An alternative execution path occurs when the range between the lower and upper limits will not fit within an int. This results in a different performance figure.

Note the last three methods which are extra methods not present on System.Random. NextUint() is provided because uint is the underlying data type behind FastRandom and so is very fast to generate. NextInt() returns an int (Int32<?CODE>) but unlike Next() the range is between 0 and int.MaxValue instead of between 0 and int.MaxValue-1. This subtle difference allows an optimization to be made (elimination of an 'if' statement). NextBool() is implemented by generating 32 bits (uint) and buffering them for future calls, hence the high speed.

Conclusion

System.Random is actually very fast and achieves its speed mostly by only using simple and fast arithmetic operations such as shift and add. However, the whole class is based around a central Sample() method that returns a double between 0.0 and 1.0, and thus there is some unnecessary floating point arithmetic used to generate integer values. FastRandom utilizes a completely different algorithm for generating random numbers that is inherently slightly faster, and in FastRandom we provide a further boost by avoiding floating point arithmetic wherever possible and implementing some further refinements. Finally, FastRandom also allows for fast re-seeding which allows repeat random number sequences to be re-generated very quickly.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

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

GeneralRe: Fast - but not very random Pin
cargo.dk18-Nov-06 7:34
cargo.dk18-Nov-06 7:34 
GeneralRe: Fast - but not very random Pin
Vandretta15-Jun-07 20:26
Vandretta15-Jun-07 20:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.