简单的伪随机算法

时间:2009-10-08 13:50:09

标签: c# random test-data

我需要一个伪随机生成器,它将一个数字作为输入并返回另一个可重现的数字,并且似乎是随机的。

  • 每个输入数字应恰好与一个输出数字相匹配,反之亦然
  • 相同的输入数字始终会产生相同的输出数字
  • 靠近在一起的顺序输入数字(例如1和2)应该产生完全不同的输出数字(例如,1 => 9783526,2 => 283)

它一定不是完美的,它只是创建随机但可重现的测试数据。

我使用C#。


我前段时间编写了这段有趣的代码,它产生了随机的东西。

  public static long Scramble(long number, long max) 
  {
    // some random values 
    long[] scramblers = { 3, 5, 7, 31, 343, 2348, 89897 };
    number += (max / 7) + 6;
    number %= max;
    // shuffle according to divisibility
    foreach (long scrambler in scramblers) 
    {
      if (scrambler >= max / 3) break;
      number = ((number * scrambler) % max) 
        + ((number * scrambler) / max);
    }

    return number % max;
  }

我希望有更好,更可靠的东西,使用任何数量的大小(没有最大参数)。

这可能是使用CRC算法解决的吗?或者有点洗牌。

4 个答案:

答案 0 :(得分:4)

我从这个答案中删除了微软代码,GNU代码文件要长得多,但基本上它包含来自http://cs.uccs.edu/~cs591/bufferOverflow/glibc-2.2.4/stdlib/random_r.c

int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;

为了你的目的,种子是状态[0]所以它看起来更像

int getRand(int val)
{
    return ((val * 1103515245) + 12345) & 0x7fffffff;
}

答案 1 :(得分:3)

您(也许)可以使用Random类在C#中轻松完成此任务:

public int GetPseudoRandomNumber(int input)
{
    Random random = new Random(input);
    return random.Next();
}

由于您使用输入显式播种Random,因此每次给定相同的输入值时,您将获得相同的输出。

答案 2 :(得分:1)

前两条规则建议输入的固定或输入种子排列,但第三条规则需要进一步转换。

对输出应该是什么有进一步的限制,以指导这种转变? - 例如是否有一组输入值可供选择?

如果唯一指南是“no max”,我会使用以下内容......

  1. 将哈希算法应用于整个输入以获取第一个输出项。 CRC可能有效,但对于更多“随机”结果,请使用加密哈希算法,例如MD5。

  2. 在输入上使用下一个排列算法(Google上有大量链接)。

  3. 重复hash-then-next-permutation,直到找到所有必需的输出。

  4. 下一个排列可能有点矫枉过正,你可能只是在重做哈希值之前增加第一个输入(也许,在溢出时增加第二个等等)。

    对于加密样式哈希,你需要一个密钥 - 在开始之前从输入中获取一些东西。

答案 3 :(得分:1)

tausworthe发电机易于实施且速度非常快。以下伪代码实现具有完整周期(2 ** 31 - 1,因为零是固定点):

def tausworthe(seed)
  seed ^= seed >> 13
  seed ^= seed << 18
  return seed & 0x7fffffff

我不知道C#,但我假设它具有XOR(^)和位移(<<>>)运算符,如C中所示。

设置初始种子值,并使用seed = tausworthe(seed)调用。