这个算法有名字吗? (我一直称它为changeBinary)
描述:
您将二进制字符串作为输入。
输出的第一位与输入的第一位相同。
如果输入字符串的索引处的位与输入字符串中前一个索引处的位相同,则此后的每个位都为0。否则,它是1。
例如,
输入:00011000001010100001001000010011
输出:00010100001111110001101100011010
这是一个简单的javascript实现:
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
观察:
首先,似乎如果继续将算法应用于字符串,它最终会返回其原始值。其次,它所需的迭代次数似乎总是2的幂(包括2 ^ 0 = 1)。例如,如果将changeBinary函数应用于上面的字符串32次以上,它将返回原始值。
以前有没有人遇到过这个问题,如果有的话,你知道有关它的任何其他信息吗?
在我看来,这是一个非常简单和基本的东西,有人必须更深入地研究它。
非常感谢任何反馈。
答案 0 :(得分:6)
可能有趣的是,在BigInteger上知道这是x ^ (x << 1)
(或者,如果你限制字符串的长度,同样的东西,但是在固定大小的整数上),也可以描述为{{1 }}
无进行乘法,基本上就像普通乘法一样,但不是添加你对它们进行异或的部分乘积,而是具有一些相当不错的属性,例如可交换和关联。关联属性尤其令人感兴趣,因为它允许您轻松地推理出几次构成算法的算法:例如
clmul(x, 3)
为changeBinary o changeBinary
它是3的无载乘法也解释了它为什么&#34;撤消&#34;当经常应用足够时,因为3的无进位乘法逆是所有位设置的数,其中32位是0xffffffff,其可以形成为3 31 (具有无进位取幂)。这也是由无进位 square 与&#34; bit-spread&#34;的等价性得出的,所以它需要一个字符串abcd到a0b0c0d,因此clmul(clmul(x, 3), 3) = clmul(x, clmul(3, 3)) = clmul(x, 5)
- 5个点差将这些位分开得那么远,只剩下原来的lsb,其余的不适合32位数。
这也提供了更快的反转,因为所有位设置的数字可以分解为少量(无进位)因子:
clpow(3, 32) = 1
有许多因素是比特数的基数2对数(向上舍入)。
由于3 x 5 x 17 x 257 x 65537 ...
会将数字转换为格雷码,我想您可能会将其称为&#34;镜像&#34;格雷码。在镜像中使用与因子相同的技巧&#34;&#34;将格雷码转换回二进制:
x ^ (x >> 1)
在这里,我们只是转移转变的方向:
x ^= x >> 1 // this is like a "mirror" of x = clmul(x, 3)
x ^= x >> 2 // 5
x ^= x >> 4 // 17
x ^= x >> 8
x ^= x >> 16
哪个是x ^= x << 1
x ^= x << 2
x ^= x << 4
x ^= x << 8
x ^= x << 16
,也被称为clmul(x, 0xffffffff)
答案 1 :(得分:0)
您描述的算法是Delta Encoding的示例。