【发布时间】:2023-04-05 03:44:01
【问题描述】:
假设我有一些数字组成一个系列 例如:652,328,1,254 我想得到一个种子,例如,如果我这样做
srand(my_seed);
我会得到某种对我的原始序列有界误差的近似值, 当所有数字以相同的顺序出现时。
【问题讨论】:
-
暂时没有,只是为了好奇。
假设我有一些数字组成一个系列 例如:652,328,1,254 我想得到一个种子,例如,如果我这样做
srand(my_seed);
我会得到某种对我的原始序列有界误差的近似值, 当所有数字以相同的顺序出现时。
【问题讨论】:
取决于用于伪随机生成的算法。如果算法是简单的linear congruential generator,那么取回种子只是求解线性模方程的问题(请注意,解可能是非唯一的,但由于这样的生成器是无记忆的,它不会问题)。
如果算法更复杂,这可能是不可能的。
请注意,C标准库中使用的算法不受标准限制,因此不同的平台可能有不同的实现。
【讨论】:
setstate 来配置glibc 以使用LCG;但是那个 LCG 只有 32 位状态,所以充其量你可以选择输出的前 32 位。之后的一切都是确定性的。
srand 在您的平台上采用 32 位参数,您最多可以请求 2^32 个不同的序列。但当然,可能的序列远不止于此,即使您只想重现非常短的序列。
一般情况下,您不能有错误限制。您的算法要么有效,要么无效。这样做的原因是合理的误差界限显然比 RAND_MAX 小得多。这反过来意味着低位不像高位那样随机。但是一个好的 PRNG 可以确保所有位都是同样随机的。
考虑这个缓慢但数学上合理的 RNG 算法示例:
int rand() {
state = AES_encrypt(state);
return state % RAND_MAX;
}
void srand(int seed) {
state = AES_encrypt(seed);
}
如果您发现输出序列与之前的state 之间存在任何显着相关性,则应认为AES 算法已损坏。
【讨论】:
看看这个question。
就像贾斯汀所说,当您有一系列生成的数字时,可以回溯线性全等生成器(rand() 实现通常是这样)。我想问题是要知道以前的哪个值是原始种子...
【讨论】:
rand() 是 LCG 即坏的要求在哪里?
rand() 和 LCG 没有任何要求,这正是大多数实现似乎是的(我已经编辑了答案以更清楚地说明这一点)。此外,LCG 并不一定很糟糕 - 它的计算速度非常快,而且在许多情况下提供的伪随机性很好。
在加密 PRNG 的定义中,这个确切的属性在计算上是不可行的 - 然而,正如已经提到的,有许多更弱(并且更快)的 PRNG 是可能的。所以这取决于你的算法。
【讨论】: