如何使用改组来提高rng?

时间:2019-06-03 15:56:26

标签: c#

下面是Bays&Durham的伪代码实现,我正在尝试使用c#中的内置随机数对随机数序列进行排序。

我遵循的伪代码是:

  1. 生成随机数(V)的数组

  2. 会生成一个随机数(Y)-种子应该是数组中的最后一个数字

  3. 使用以下公式生成随机索引(y):(K * Y)/ m 哪里: K-数组大小 Y-生成的随机数 M-用于填充数组的随机数生成器中使用的模数

  4. 返回数组Y位置处的元素,即V [y]

  5. 数组中Y位置的元素本身设置为Y,即V [y] = Y

int[] seq = GetRand(size, min, max);
int nextRand = cRNG.Next(seq[seq.Length-1]);

//int index = (seq.Length * nextRand) / [Add Modulus];

return seq;

我可以遵循的前几个步骤。现在,我需要返回一个改组后的数组,因此需要对伪代码进行一些修改。

上面的代码很少有指针: cRNG-> Random的实例名称 GetRand(...)->使用cRNG进行forloop

现在我不了解的是以下内容:

1)鉴于我正在使用内置随机变量,如何获得用于填充数组的模数,因为它只是使用cRNG.Next(min,max)的for循环

2)最后一步,我还不完全了解

任何帮助将不胜感激!

[编辑]

按照塞缪尔·维达(Samuel Vidal)的解决方案行之有效? (假设我必须用一种方法完成所有操作)

public static int[] Homework(int size, int min, int max)
{
    var seq = GetRand(size, min, max);
    nextRand = cRNG.Next(min, max);

    var index = (int) ((seq.Length * (double) (nextRand - min)) / (max - min));
    nextRand = seq[index];
    seq[index] = cRNG.Next(min, max);

    return sequence;  // nextRand that should be returned instead.
// Made it return the array because it should return the newly shuffled array hence the for loop
}

1 个答案:

答案 0 :(得分:0)

我认为您想要的是以下

var index = (int) ((sequence.Length * (double)(randNum - min)) / (max - min));

但是我建议您使用源中未更改的随机数填充数组,然后将随机数生成器的输出映射为区间[min, max[作为重载方法Next(int min, int max)来调用, Bays-Durham随机播放过程的输出。

public class BaysDurham
{
    private readonly int[] t;
    private int y; // auxiliary variable

    // Knuth TAOCP 2 p. 34 Algorithm B

    public BaysDurham(int k)
    {
        t = new int[k];

        for (int i = 0; i < k; i++)
        {
            t[i] = rand.Next();
        }

        y = rand.Next();
    }

    public int Next()
    {
        var i = (int)(((long) t.Length * y) / int.MaxValue);
        y = t[i];
        t[i] = rand.Next();
        return y;
    }

    public int Next(int min, int max)
    {
        long m = max - min;
        return min + (int) ((Next() * m) / int.MaxValue);
    }

    private readonly Random rand = new Random();
}

通常,拥有separation of concerns是一个很棒的软件设计原则。


测试代码:

[Test]
public void Test()
{
    const int k = 30;
    const int n = 1000 * 1000;

    const int min = 10;
    const int max = 27;

    var rng = new BaysDurham(k);

    var count = new int[max];

    for (int i = 0; i < n; i++)
    {
        var index = rng.Next(min, max);
        count[index] ++;
    }

    Console.WriteLine($"Expected : {1.0 / (max - min):F4}, Actual :");

    for (int i = min; i < max; i++)
    {
        Console.WriteLine($"{i} : {count[i] / (double) (n):F4}");
    }
}

结果:

Expected : 0.0588, Actual :
10 : 0.0584
11 : 0.0588
12 : 0.0588
13 : 0.0587
14 : 0.0587
15 : 0.0589
16 : 0.0590
17 : 0.0592
18 : 0.0586
19 : 0.0590
20 : 0.0586
21 : 0.0588
22 : 0.0586
23 : 0.0587
24 : 0.0590
25 : 0.0594
26 : 0.0590