代码之家  ›  专栏  ›  技术社区  ›  Stefan Steinegger

简单伪随机算法

  •  5
  • Stefan Steinegger  · 技术社区  · 15 年前

    我需要一个伪随机生成器,它以一个数字作为输入,并返回另一个数字,开关是可复制的,似乎是随机的。

    • 每个输入数字应恰好与一个输出数字匹配,反之亦然。
    • 相同的输入数字总是产生相同的输出数字
    • 相邻的顺序输入数字(如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 回复  |  直到 10 年前
        1
  •  3
  •   MusiGenesis    15 年前

    你(也许)可以很容易地在C中使用随机类:

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

    因为您是使用输入显式地随机播种的,所以每次给定相同的输入值时,您都会得到相同的输出。

        2
  •  4
  •   John Boker    15 年前

    我从这个答案中删除了Microsoft代码,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;
    }
    
        3
  •  1
  •   Steve314    15 年前

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

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

    如果唯一的指南是“没有最大值”,我会用下面的…

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

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

    3. 重复散列,然后进行下一个排列,直到找到所有必需的输出。

    但是,下一个排列可能是杀伤力过大,在重做哈希之前,您可能只需要增加第一个输入(或者,在溢出时,增加第二个输入,等等)。

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

        4
  •  1
  •   pjs    10 年前

    一个tausworth生成器实现简单,速度相当快。以下伪代码实现具有完整的周期(2**31-1,因为零是一个固定点):

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

    我不知道C,但我假设它有XOR( ^ )比特移位( << , >> )C中的运算符。

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