【问题标题】:How to use Shuffling to improve rng?如何使用 Shuffle 来提高 rng?
【发布时间】:2019-06-03 15:56:26
【问题描述】:

按照 Bays & Durham 的伪代码实现,我尝试使用 c# 中的内置随机数对随机数字序列进行排序。

我下面的伪代码是:

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

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

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

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

  5. 数组中位置 Y to 的元素设置为 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
}

【问题讨论】:

  • 这个的用例是什么?
  • 使用 Shuffle 改进随机数的序列
  • 好的,您所说的“改进”是什么意思?这只是一个学术练习/家庭作业吗?因为否则,已经有一个 PRNG 可供您使用,它比您或我可以编写的更好。
  • 我认为你的第2步已经错了,因为你没有使用数组中的最后一个数字作为种子
  • @Doomsayer 是的,但你没有将它用作种子

标签: c#


【解决方案1】:

我认为您想要的是以下内容,

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

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

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

【讨论】:

    猜你喜欢
    • 2014-11-05
    • 1970-01-01
    • 2020-08-31
    • 2014-03-04
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 2021-01-08
    • 2014-04-09
    相关资源
    最近更新 更多