【发布时间】:2010-11-25 04:45:42
【问题描述】:
我正在使用基本转换算法从大整数(拆分为 32 位字)生成排列。
我为此使用了一个相对标准的算法:
/* N = count,K is permutation index (0..N!-1) A[N] contains 0..N-1 */
i = 0;
while (N > 1) {
swap A[i] and A[i+(k%N)]
k = k / N
N = N - 1
i = i + 1
}
不幸的是,每次迭代的除法和模数加起来,尤其是移动到大整数 - 但是,我似乎可以只使用乘法!
/* As before, N is count, K is index, A[N] contains 0..N-1 */
/* Split is arbitrarily 128 (bits), for my current choice of N */
/* "Adjust" is precalculated: (1 << Split)/(N!) */
a = k*Adjust; /* a can be treated as a fixed point fraction */
i = 0;
while (N > 1) {
a = a*N;
index = a >> Split;
a = a & ((1 << Split) - 1); /* actually, just zeroing a register */
swap A[i] and A[i+index]
N = N - 1
i = i + 1
}
这更好,但做大整数乘法仍然很慢。
问题 1:
有没有更快的方法?
例如。既然我知道 N*(N-1) 小于 2^32,我可以从一个单词中提取这些数字,并合并到“剩菜”中吗?
或者,有没有办法修改算术解码器以一次提取一个索引?
问题 2:
出于好奇 - 如果我使用乘法将数字转换为以 10 为底的数字而不进行调整,则结果将乘以 (10^digits/2^shift)。有没有一种棘手的方法来消除这个与十进制数字一起工作的因素?即使有调整因素,这似乎会更快——为什么标准库不使用这个与除法和模法?
【问题讨论】:
-
我无法理解你的第二种算法。
-
@GregS - 如果您认为有问题,请告诉我 - 理论是它使用乘法/掩码从左侧 (msb) 删除值,而使用 mod/divide 从右侧 (lsb) 删除值。
标签: c algorithm optimization math