从种子随机数 [英] Random number from a seed

查看:178
本文介绍了从种子随机数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如果我的程序使用基于其种子模式的RNG它变得格外引人注目的应用程序,因为它基于对景观的x坐标构建景观。而随机工作得很好,如果你调用下一页()每一次,我需要能够具有相同输出我每次使用相同的输入,因此不能依靠下一次()。相反,我试图简单地做一个新的随机与输入种子每次。不是一个很好的主意,我知道,它显示。这些图案都非常明显,交替高低值,整个景观的显着的总体趋势。我不想每次都作出新的发电机,但即便如此,我看着加密安全 RandomNumberGenerator 来看看我是否能至少暂时使用它。正如预期的那样,虽然,我不能播种了,留下我没有任何类型可重复的输出(这是相当的点 RandomNumberGenerator )。

I have an application where it becomes extremely noticeable if my program uses an RNG that has patterns based on its seed, as it builds landscapes based on the x coordinate of the landscape. While Random works well if you're calling Next() every time, I need to be able to have the same output every time I use the same input, and thus can't rely on Next(). Instead, I attempted to simply make a new Random every time with the input seed. Not a very good idea, I know, and it showed. The patterns were extremely obvious, with alternating high and low values, and an noticeable overall trend across the entire landscape. I'd prefer not to be making new generators every time, but even so, I looked into the cryptographically secure RandomNumberGenerator to see if I could at least use it temporarily. As expected, though, I can't seed it, leaving me without any sort of reproducible output (which is rather the point of the RandomNumberGenerator).

在总之,无论是两种常见的RNG的出现,以适应我的目的。我需要能够采取在一个电话号码,并返回一个随机数的基础上,而不在输出显型态该值。是否有其他方式使用上述两个,还是有我在此之前没有使用会更适合我的目的第三?

In short, neither of the two common RNGs appear to suit my purpose. I need to be able to take in a a number and return a random number based on that value without noticeable patterns in the output. Is there another way to use the above two, or is there a third I haven't used before that would better suit my purpose?

有关清晰,方法我米试图写看起来像这样:

For clarity, the method I'm trying to write looks like so:

public int RandomInt(int input)
{
    int randomOutput;
    //Be random
    return randomOutput;
}

这将每次返回相同的值相同的输入给定

That will return the same value every time the same input is given.

推荐答案

一个的 梅森倍捻机 可能的给出更好的结果。

A Mersenne Twister might give better results.

下面是一个示例实现,你应该能够很快地尝试:

Here's a sample implementation that you should be able to try out fairly quickly:

using System;

namespace Random
{
    /* C# Version Copyright (C) 2001 Akihilo Kramot (Takel).       */
    /* C# porting from a C-program for MT19937, originaly coded by */
    /* Takuji Nishimura, considering the suggestions by            */
    /* Topher Cooper and Marc Rieffel in July-Aug. 1997.           */
    /* This library is free software under the Artistic license:   */
    /*                                                             */
    /* You can find the original C-program at                      */
    /* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html    */
    /*                                                             */

    /// <summary>
    /// Implements a Mersenne Twister Random Number Generator. This class provides the same interface
    /// as the standard System.Random number generator, plus some additional functions.
    /// </summary>

    public class MersenneTwister: System.Random
    {
        /* Period parameters */
        private const int N = 624;
        private const int M = 397;
        private const uint MATRIX_A = 0x9908b0df; /* constant vector a */
        private const uint UPPER_MASK = 0x80000000; /* most significant w-r bits */
        private const uint LOWER_MASK = 0x7fffffff; /* least significant r bits */

        /* Tempering parameters */
        private const uint TEMPERING_MASK_B = 0x9d2c5680;
        private const uint TEMPERING_MASK_C = 0xefc60000;

        private static uint TEMPERING_SHIFT_U( uint y ) { return ( y >> 11 ); }
        private static uint TEMPERING_SHIFT_S( uint y ) { return ( y << 7 ); }
        private static uint TEMPERING_SHIFT_T( uint y ) { return ( y << 15 ); }
        private static uint TEMPERING_SHIFT_L( uint y ) { return ( y >> 18 ); }

        private uint[] mt = new uint[N]; /* the array for the state vector  */

        private uint seed_;
        private short mti;

        private static uint[] mag01 = { 0x0, MATRIX_A };

        /// <summary>
        /// Create a twister with the specified seed. All sequences started with the same seed will contain
        /// the same random numbers in the same order.
        /// </summary>
        /// <param name="seed">The seed with which to start the twister.</param>

        public MersenneTwister( uint seed )
        {
            Seed = seed;
        }


        /// <summary>
        /// Create a twister seeded from the system clock to make it as random as possible.
        /// </summary>

        public MersenneTwister()
            : this( ( (uint) DateTime.Now.Ticks ) )  // A random initial seed is used.
        {
        }


        /// <summary>
        /// The seed that was used to start the random number generator.
        /// Setting the seed resets the random number generator with the new seed.
        /// All sequences started with the same seed will contain the same random numbers in the same order.
        /// </summary>

        public uint Seed
        {
            set
            {
                seed_ = value;

                /* setting initial seeds to mt[N] using         */
                /* the generator Line 25 of Table 1 in          */
                /* [KNUTH 1981, The Art of Computer Programming */
                /*    Vol. 2 (2nd Ed.), pp102]                  */

                mt[0] = seed_ & 0xffffffffU;
                for ( mti = 1; mti < N; mti++ )
                {
                    mt[mti] = ( 69069 * mt[mti - 1] ) & 0xffffffffU;
                }
            }

            get
            {
                return seed_;
            }
        }


        /// <summary>
        /// Generate a random uint.
        /// </summary>
        /// <returns>A random uint.</returns>

        protected uint GenerateUInt()
        {
            uint y;

            /* mag01[x] = x * MATRIX_A  for x=0,1 */

            if ( mti >= N ) /* generate N words at one time */
            {
                short kk;

                for ( kk = 0; kk < N - M; kk++ )
                {
                    y = ( mt[kk] & UPPER_MASK ) | ( mt[kk + 1] & LOWER_MASK );
                    mt[kk] = mt[kk + M] ^ ( y >> 1 ) ^ mag01[y & 0x1];
                }

                for ( ; kk < N - 1; kk++ )
                {
                    y = ( mt[kk] & UPPER_MASK ) | ( mt[kk + 1] & LOWER_MASK );
                    mt[kk] = mt[kk + ( M - N )] ^ ( y >> 1 ) ^ mag01[y & 0x1];
                }

                y = ( mt[N - 1] & UPPER_MASK ) | ( mt[0] & LOWER_MASK );
                mt[N - 1] = mt[M - 1] ^ ( y >> 1 ) ^ mag01[y & 0x1];

                mti = 0;
            }

            y = mt[mti++];
            y ^= TEMPERING_SHIFT_U( y );
            y ^= TEMPERING_SHIFT_S( y ) & TEMPERING_MASK_B;
            y ^= TEMPERING_SHIFT_T( y ) & TEMPERING_MASK_C;
            y ^= TEMPERING_SHIFT_L( y );

            return y;
        }


        /// <summary>
        /// Returns the next uint in the random sequence.
        /// </summary>
        /// <returns>The next uint in the random sequence.</returns>

        public virtual uint NextUInt()
        {
            return this.GenerateUInt();
        }


        /// <summary>
        /// Returns a random number between 0 and a specified maximum.
        /// </summary>
        /// <param name="maxValue">The upper bound of the random number to be generated. maxValue must be greater than or equal to zero.</param>
        /// <returns>A 32-bit unsigned integer greater than or equal to zero, and less than maxValue; that is, the range of return values includes zero but not MaxValue.</returns>

        public virtual uint NextUInt( uint maxValue )
        {
            return (uint) ( this.GenerateUInt() / ( (double) uint.MaxValue / maxValue ) );
        }


        /// <summary>
        /// Returns an unsigned random number from a specified range.
        /// </summary>
        /// <param name="minValue">The lower bound of the random number returned.</param>
        /// <param name="maxValue">The upper bound of the random number returned. maxValue must be greater than or equal to minValue.</param>
        /// <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.</returns>

        public virtual uint NextUInt( uint minValue, uint maxValue ) /* throws ArgumentOutOfRangeException */
        {
            if (minValue >= maxValue)
            {
                if (minValue == maxValue)
                {
                    return minValue;
                }
                else
                {
                    throw new ArgumentOutOfRangeException("minValue", "NextUInt() called with minValue >= maxValue");
                }
            }

            return (uint) ( this.GenerateUInt() / ( (double) uint.MaxValue / ( maxValue - minValue ) ) + minValue );
        }


        /// <summary>
        /// Returns a nonnegative random number.
        /// </summary>
        /// <returns>A 32-bit signed integer greater than or equal to zero and less than int.MaxValue.</returns>

        public override int Next()
        {
            return (int) ( this.GenerateUInt() / 2 );
        }


        /// <summary>
        /// Returns a nonnegative random number less than the specified maximum.
        /// </summary>
        /// <param name="maxValue">The upper bound of the random number to be generated. maxValue must be greater than or equal to zero.</param>
        /// <returns>A 32-bit signed integer greater than or equal to zero, and less than maxValue;
        /// that is, the range of return values includes zero but not MaxValue.</returns>

        public override int Next( int maxValue ) /* throws ArgumentOutOfRangeException */
        {
            if ( maxValue <= 0 )
            {
                if ( maxValue == 0 )
                    return 0;
                else
                    throw new ArgumentOutOfRangeException( "maxValue", "Next() called with a negative parameter" );
            }

            return (int) ( this.GenerateUInt() / ( uint.MaxValue / maxValue ) );
        }


        /// <summary>
        /// Returns a signed random number from a specified range.
        /// </summary>
        /// <param name="minValue">The lower bound of the random number returned.</param>
        /// <param name="maxValue">The upper bound of the random number returned. maxValue must be greater than or equal to minValue.</param>
        /// <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.</returns>

        public override int Next( int minValue, int maxValue ) /* ArgumentOutOfRangeException */
        {
            if (minValue >= maxValue)
            {
                if (minValue == maxValue)
                {
                    return minValue;
                }
                else
                {
                    throw new ArgumentOutOfRangeException("minValue", "Next() called with minValue > maxValue");
                }
            }

            return (int) ( this.GenerateUInt() / ( (double) uint.MaxValue / ( maxValue - minValue ) ) + minValue );
        }


        /// <summary>
        /// Fills an array of bytes with random numbers from 0..255
        /// </summary>
        /// <param name="buffer">The array to be filled with random numbers.</param>

        public override void NextBytes( byte[] buffer ) /* throws ArgumentNullException*/
        {
            int bufLen = buffer.Length;

            if ( buffer == null )
                throw new ArgumentNullException("buffer");

            for ( int idx = 0; idx < bufLen; idx++ )
                buffer[idx] = (byte) ( this.GenerateUInt() / ( uint.MaxValue / byte.MaxValue ) );
        }


        /// <summary>
        /// Returns a double-precision random number in the range [0..1[
        /// </summary>
        /// <returns>A random double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>

        public override double NextDouble()
        {
            return (double) this.GenerateUInt() / uint.MaxValue;
        }
    }
}

这篇关于从种子随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆