说我有二进制数0b00110101
。
是否有一组琐碎的算术运算会产生0b0000111100110011
,其中第一个单词的每一位都重复两次?
是否存在重复位3,4或N次的这种微不足道的功能?
答案 0 :(得分:9)
看一下这个文件:
它描述了交织两个16位数字,将它扩展为32位数字(这创建了一个64位数字)是相当简单的。您只需继续该模式一个额外的周期。像这样:
static const unsigned long long B[] = {
0x5555555555555555,
0x3333333333333333,
0x0F0F0F0F0F0F0F0F,
0x00FF00FF00FF00FF,
0x0000FFFF0000FFFF
};
static const unsigned int S[] = {1, 2, 4, 8, 16};
unsigned long long x; // x must initially fit inside 32 bits
unsigned long long z; // z gets the result of x interleaved with itself
x = (x | (x << S[4])) & B[4];
x = (x | (x << S[3])) & B[3];
x = (x | (x << S[2])) & B[2];
x = (x | (x << S[1])) & B[1];
x = (x | (x << S[0])) & B[0];
z = x | (x << 1);
答案 1 :(得分:1)
我会做一张桌子 - 这可能是最快捷的方式。
你当然可以这样做:
int doublebits(int x)
{
int y = 0;
int bit = 0;
while(x)
{
if (x & 1)
y |= 3 << bit;
bit += 2;
x >>= 1;
}
return y;
}
对于8位数字,您最多可以向下移动8次,向右移动8次以获得新数字。
答案 2 :(得分:0)
好的,这次我相信找到了正确的顺序:
http://oeis.org/search?q=3%2C12%2C15%2C48&sort=&language=&go=Search
他们建议生产它的一种方式是递归地:
a(2n)= 4a(n),a(2n + 1)= 4a(n)+3。
这不过是微不足道的。
答案 3 :(得分:0)
看here,似乎技术需要LUT或循环。所以,我认为最优雅的方法是在计算之前设置y = x
时使用“明显的方式”(链接)。
unsigned short x; // Interleave bits of x and y, so that all of the
unsigned short y; // bits of x are in the even positions and y in the odd;
unsigned int z = 0; // z gets the resulting Morton Number.
x = INPUT_PATTERN;
y = x;
for (int i = 0; i < sizeof(x) * CHAR_BIT; i++) // unroll for more speed...
{
z |= (x & 1U << i) << i | (y & 1U << i) << (i + 1);
}
是的,我知道它不一定是OP要求的“聪明”解决方案,但到目前为止的其他答案还包括循环/递归,所以为什么不尝试一下......