如何在C#中编写线性同余发生器(LCG)?或者有任何众所周知的实现?

时间:2010-10-14 16:26:37

标签: c# algorithm random

我想生成一个重复的随机序列,只使用每个数字一次。例如,给定0-9的范围,有2个不同的种子,你可能会得到

Seed 1: 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4
Seed 2: 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0

根据我的理解,线性同余随机数发生器或LCRNG或LCG可以给我这个http://en.wikipedia.org/wiki/Linear_congruential_generator

知道C#中是否存在实现,或者我是如何开始编写实现的。

Mersenne Twister与LCG有何不同?

不确定我的所有问题都得到了解答,但这是我最终使用的问题。因为我将样本大小限制在从max到min的值范围内,所以只要给出相同的初始种子,我就选择保持静态的不同素数。我这样做是因为我想要相同的序列给出相同的种子和相同的最小/最大界限,以确保测试的可重复性。

请批评我在这里做的任何事情,这正是我在一瞬间提出的:

using System;
using System.Collections.Generic;

namespace FULLCYCLE
{
    public class RandomNumber
    {
        private int _value;
        private int _prime;
        private static List<int> primes = new List<int>()
        {
            11,
            23,
            47,
            97,
            797,
            1597,
            6421,
            25717,
            51437,
            102877,
            411527,
            823117,
            1646237,
            3292489,
            6584983,
            13169977,
            26339969,
            52679969,
            105359939,
            210719881,
            421439783,
            842879579,
            1685759167
        };

        public RandomNumber( int seed )
        {
            _prime = primes[seed%primes.Count];
            _value = seed;
        }

        public int Next( int min, int max )
        {
            int maxrate = (max-min+1);
            if (_value > maxrate)
            {
                _value = _value % maxrate;
            }

            _value = (_value + _prime) % maxrate;
            return _value + min;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

为什么不在输入序列中使用现有的Random类和Knuth shuffle

答案 1 :(得分:1)

关于您的编辑,您的LCG作为随机数生成器有几个问题......

  1. 它可以产生明显的模式:

    // generates 3, 4, 5, 6, 7, 8, 9, 0, 1, 2
    var rng = new RandomNumber(42);
    for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(0, 9));
    
  2. 它可以重演:

    // generates 579, 579, 579, 579, 579, 579, 579, 579, 579, 579
    var rng = new RandomNumber(123);
    for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(456, 51892));
    
  3. 还有许多其他种子/最小/最大组合会产生有问题的结果。