5

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

  • 每个输入数字应与一个输出数字完全匹配,反之亦然
  • 相同的输入数字总是导致相同的输出数字
  • 靠近的连续输入数字(例如 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

4 回答 4

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;

出于您的目的,种子是 state[0] 所以它看起来更像

int getRand(int val)
{
    return ((val * 1103515245) + 12345) & 0x7fffffff;
}
于 2009-10-08T13:59:00.903 回答
3

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

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

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

于 2009-10-08T13:54:24.453 回答
2

tausworthe 生成器易于实现且速度非常快。以下伪代码实现具有完整的周期(2**31 - 1,因为零是一个固定点):

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

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

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

于 2014-05-26T17:42:25.533 回答
1

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

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

如果唯一的指南是“无最大值”,我会使用以下...

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

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

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

但是,下一个排列可能有点矫枉过正,您可能只是在重做哈希之前增加第一个输入(并且可能在溢出时增加第二个输入,依此类推)。

对于加密风格的散列,您需要一个密钥 - 只需在开始之前从输入中派生一些东西。

于 2009-10-08T14:39:19.993 回答