Answers:
您需要的是0到之间的一个随机数。然后的问题是将其变成位模式。
这被称为枚举编码,它是最古老的部署压缩算法之一。可能最简单的算法来自Thomas Cover。根据简单的观察,如果您有一个单词,它的长度为位,并且设置的位以最高位顺序为,则该单词在所有具有该属性的单词的词典编排顺序中的位置是:
因此,例如,对于7位字:
...等等。
要从顺序中获取位模式,只需依次解码每个位。类似于C的语言:
uint64_t decode(uint64_t ones, uint64_t ordinal)
{
uint64_t bits = 0;
for (uint64_t bit = 63; ones > 0; --bit)
{
uint64_t nCk = choose(bit, ones);
if (ordinal >= nCk)
{
ordinal -= nCk;
bits |= 1 << bit;
--ones;
}
}
return bits;
}
请注意,由于只需要不超过64的二项式系数,因此可以对其进行预先计算。
与通过其他方式获得的Pseudonym的答案非常相似。
可用组合的总数可以通过stars and bars方法达到,因此必须为。您尝试从中采样数字的64位数字总数显然要高得多。
然后您需要的是一个函数,可以将您从一个伪随机数(从到引导到相应的64位组合。
Pascal的三角形可以为您提供帮助,因为每个节点的值都精确地代表了从该节点到三角形根的路径数,并且如果所有的左转都是,则每个路径都可以代表您要查找的字符串之一。标记为,每个右转标记为。
因此,令为要确定的剩余位数,而为要使用的剩余位数。
我们知道,我们可以使用它来正确确定数字的下一位在每一步:
另一个相当优雅的方法是使用stackoverflow答案中所述的二等分。想法是保留两个单词,一个已知最多设置k个位,另一个已知至少设置k个位,并使用随机性将其中之一移到恰好具有k个位。以下是一些说明它的源代码:
word randomKBits(int k) {
word min = 0;
word max = word(~word(0)); // all 1s
int n = 0;
while (n != k) {
word x = randomWord();
x = min | (x & max);
n = popcount(x);
if (n > k)
max = x;
else
min = x;
}
return min;
}
您可以执行以下操作:
1)产生到之间的随机数。
2)将 th设置为。
3)重复步骤1和2次
是全的位数组
for(i=1 to n)
{
k=ran(1,65-i) % random number between 1 and 65-i
for(x=1;x<65;x++)
{
if(A[x]==0)k--;
if(k==0)break;
}
A[x]=1;
}
1
s 分配给数组。同样,当多个k
s碰撞时,它似乎并没有产生均匀的分布(甚至没有满足约束的数字)