随机数生成以及之前和之前的支持?

时间:2014-08-06 19:46:21

标签: algorithm random

如何编写两个函数来生成支持next和previous的随机数?

我的意思是如何编写两个函数:next_number()previous_number()next_number()函数生成一个新的随机数,previous_number()函数生成以前生成的随机数。

例如:

int next_number()
{
   // ...?
}

int previous_number()
{
   // ...?
}

int num;

// Forward random number generating.
// ---> 54, 86, 32, 46, 17
num = next_number(); // num = 54
num = next_number(); // num = 86
num = next_number(); // num = 32
num = next_number(); // num = 46
num = next_number(); // num = 17

// Backward random number generating.
// <--- 17, 46, 32, 86, 54
num = previous_number(); // num = 46
num = previous_number(); // num = 32
num = previous_number(); // num = 86
num = previous_number(); // num = 54

5 个答案:

答案 0 :(得分:5)

您可以使用伪随机函数(PRF)轻松完成此操作。

这些函数接受一个键和一个值,并根据它们输出一个伪随机数。您可以从/ dev / random中选择一个对于程序运行保持不变的键,然后向该函数提供一个整数,您可以将其递增以前进或递减以返回。

以下是伪代码中的示例:

initialize():
    Key = sufficiently many bytes from /dev/random
    N = 0

next_number():
    N = N + 1
    return my_prf(Key, N)

previous_number():
    N = N - 1
    return my_prf(Key, N)

在大多数加密库中都可以找到强大的伪随机函数。正如rici指出的那样,你也可以使用任何加密函数(加密函数是伪随机排列,PRF的一个子集,周期非常大,差别无关紧要。)

答案 1 :(得分:3)

一些linear congruential generators(常见但不太好的PRNG)是可逆的。

他们按next = (a * previous + c) mod m工作。如果amodular multiplicative inverse mod m,那就是可逆的。通常情况如此,因为m通常是2的幂,而a通常是奇数。

例如,对于&#34; MSVC&#34;来自第一个链接的表中的参数:

  • m = 2 32
  • a = 214013
  • c = 2531011

相反的是:

previous = (current - 2531011) * 0xb9b33155;

选择使其类型为2 32 的类型。

答案 2 :(得分:2)

假设您有一个由

定义的线性同余序列S
S[0] = seed
S[i] = (p * S[i-1] + k) % m

对于某些pmkgcd(p, m) == 1。然后,您可以找到q (p * q) % m == 1和计算:

S[i-1] = (q * (S[i] - k)) % m

换句话说:如果您选择合适的p并预先计算q,您可以在O(1)时间内以任意顺序遍历您的序列。

答案 3 :(得分:2)

生成可索引伪随机序列的一种相当简单的方法 - 即,看起来是随机的,但可以在任一方向上遍历的序列 - 是选择一些(相当好的)加密算法和固定的加密密钥,然后定义:

sequence(i): encrypt(i, known_key)

您不需要知道i的价值,因为您可以从数字中解密它:

next(r): encrypt(decrypt(r, known_key) + 1)

prev(r): encrypt(decrypt(r, known_key) - 1)

因此,i不必是一个小整数;因为你需要做的唯一算术是用小整数加法和减法,所以bignum实现是微不足道的。因此,如果您需要128位伪随机数,可以将第一个i设置为从/dev/random中提取的128位随机数。

您必须将i的整个值保留在静态存储中,并且伪随机数的周期不能大于i的范围。但是,对于此问题的任何解决方案都是如此:由于next()prev()运算符必须是函数,因此每个值都有唯一的后继函数和前任函数,因此只能在价值循环。这与梅森捻线机完全不同,例如,其周期远大于2 32

答案 4 :(得分:0)

我认为你所要求的是确定性的随机数发生器。这没有意义,因为如果它是确定性的,那就不是随机的。唯一的解决方案是生成一个随机数列表,然后在此列表中前后移动。

PS!我知道所有软件PRNG-s都是确定性的。您当然可以使用它来创建您需要的功能,但不要欺骗自己,它与随机性无关。如果您的软件设计需要具有确定性的PRNG,那么您可以完全跳过PRNG部分。