【发布时间】:2015-06-02 09:40:40
【问题描述】:
随机问题。
我正在尝试创建一个可以生成伪随机分布的程序。我正在尝试为我的需要找到正确的伪随机算法。这些是我的担忧:
1) 每次使用时我都需要一个输入来生成相同的输出。
2) 它需要足够随机,以使查看输入 1 输出的人看不到输入 1 的输出与输入 2 的输出之间没有任何联系(等等),但不需要加密安全或真正随机的。
3) 它的输出应该是一个介于 0 和 (29^3200)-1 之间的数字,该范围内的每个可能的整数都是一个可能的且同样(或接近)可能的输出。
4) 我希望能够保证 410 个输出序列的每个可能排列也是连续输入的潜在输出。换言之,0 到 (29^3200)-1 之间的 410 个整数的所有可能分组都应该是顺序输入的潜在输出。
5) 我希望函数是可逆的,这样我就可以取一个整数或一系列整数,并说出哪个输入或输入系列会产生该结果。
到目前为止我开发的方法是通过一个简单的 halson 序列运行输入:
boost::multiprecision::mpz_int denominator = 1;
boost::multiprecision::mpz_int numerator = 0;
while (input>0) {
denominator *=3;
numerator = numerator * 3 + (input%3);
input = input/3;
}
然后将结果乘以 29^3200。它满足要求 1-3,但不满足要求 4。而且它只对单个整数可逆,而不是对数列可逆(因为不是所有数列都可以由它产生)。我在 C++ 中工作,使用 boost 多精度。
任何人可以就生成满足这些要求的随机分布的方法给我的任何建议,或者只是为此目的值得研究的一类算法,将不胜感激。提前感谢您考虑我的问题。
----更新----
由于多个评论者都关注相关数字的大小,我只是想明确表示,我认识到使用此类集合会带来的实际问题,但在提出这个问题时,我只对理论或概念感兴趣解决问题的方法 - 例如,想象使用一组更小的整数,如 0 到 99,以及 10 个输出序列的集合的排列。您将如何设计一种算法来满足这五个条件 - 1)输入是确定性的,2)出现随机(至少对人眼而言),3)范围内的每个整数都是可能的输出,4)不仅是所有值,而且值序列的所有排列都是可能的输出,5)函数是可逆的。
---第二次更新---
非常感谢@Severin Pappadeux,我能够反转 lcg。我想我会添加一些关于我所做的事情,以希望将来让任何人更容易看到这一点。首先,这些是反模函数的极好资源:
https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/modular-inverses
https://www.khanacademy.org/computer-programming/discrete-reciprocal-mod-m/6253215254052864
如果您采用等式 next=ax+c%m,则使用以下代码和您的 a 和 m 值将打印出您需要找到 ainverse 的欧几里得方程,以及 ainverse 的值:
int qarray[12];
qarray[0]=0;
qarray[1]=1;
int i =2;
int reset = m;
while (m % a >0) {
int remainder=m%a;
int quotient=m/a;
std::cout << m << " = " << quotient << "*" << a << " + " << remainder << "\n";
qarray[i] =qarray[i-2]-(qarray[i-1]*quotient);
m=a;
a=remainder;
i++;
}
if (qarray[i-1]<0) {qarray[i-1]+=reset;}
std::cout << qarray[i-1] << "\n";
我花了一段时间才弄清楚的另一件事是,如果你得到一个否定的结果,你应该给它加上 m。您应该在新方程式中添加一个类似的项:
prev = (ainverse(next-c))%m;
if (prev<0) {prev+=m;}
我希望这对将来在这条路上冒险的人有所帮助。
【问题讨论】:
-
为什么是 29^3200-1?那是巨大的;远远超出任何 C++ 类型,需要大约 15546 位来存储它。
-
这叫散列函数,可以试试%225什么的
-
我的建议是进行文献检索,找出最近在 PRNG 上工作的人,然后在合适的情况下使用他们已发表的工作,或者联系他们并支付费用来开发你想要的东西。在您指定的范围内,状态空间的隐含大小是巨大的。这类东西非常难——即使是像冯诺依曼这样杰出的数学家也有过惨痛的失败。
-
@JoshuaByer 1. md5 也是一个哈希函数 2. 已弃用
-
@JonathanBasile:我将比特数与权力混合在一起,所以我会重新开始。数字
29^3200~2^15546可以存储在 15546 位中。具有15546~2^13.924位的状态机最多可以产生一个排列。410~2^8.679输出的每个排列都将singlePermSize*410=2^(13.924+8.679)~2^22.603状态位作为理论最小值,~778 KB(您写了 6.5MB,但忘记了位->字节转换)。所以你大部分都在那儿,我离得很远
标签: c++ algorithm random permutation lcg