反转四分体(nybbles)以仅使用位操作获得镜像十六进制
Reverse tetrads (nybbles) to get a mirrored hex using bit manipulations only
我被赋予了一项有趣的任务来帮助某人;这里是:
Write a function to reverse tetrads in a number only using bit manipulations, constants, ~ ! * + - sizeof() << >> & ^ and |.
If, do, while, for, goto, switch etc. are not allowed, no macros, c++ functions (even compiler's intristic functions), &&, ||, ternary, and any other data types and structures, except for unsigned int.
这是我得到的,它可以工作,但它使用一个小循环,这是一个问题...
unsigned ReverseTetrads(unsigned x)
{
unsigned reversed = x&0xF;
while ((x >>= 4) != 0) {
reversed <<= 4;
reversed |= x&0xF;
}
return reversed;
}
示例:
0x12ABCD should be reversed to 0xDCBA21
这是我想出的:
unsigned ReverseTetrads(unsigned x)
{
unsigned
reversed = x&0xF,
offsets = 0;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed >>= (7 - offsets) * 4;
return reversed;
}
完美适用于任何 unsigned int
。
首先使用标准位 hack 反转四分体,忽略前导零:交换顶部和底部 16 位,然后交换每 16 位中的顶部和底部字节,然后交换每个字节中的顶部和底部 nybble。
然后您可以通过检查底部 16 位、底部字节和底部 nybble 是否为零并适当移位来去除前导零(现在是尾随零)。我们可以相信 !x 在值为 0 时计算为 1,否则为 0。
unsigned int ReverseTetrads(unsigned int x)
{
// reverse tetrads ignoring leading zeros
x = (x << 16) | (x >> 16);
x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff);
x = ((x << 4) & 0xf0f0f0f0) | ((x >> 4) & 0x0f0f0f0f);
// get rid of the leading zeros (which are now trailing zeros)
x >>= !(x & 0x0000ffff) * 16;
x >>= !(x & 0x000000ff) * 8;
x >>= !(x & 0x0000000f) * 4;
return x;
}
根据问题,*
是允许的,但如果您认为它不算作位操作,那么您可以用 x >>= !(x & 0x0000ffff) << 4;
代替 x >>= !(x & 0x0000ffff) * 16;
等
我被赋予了一项有趣的任务来帮助某人;这里是:
Write a function to reverse tetrads in a number only using bit manipulations, constants, ~ ! * + - sizeof() << >> & ^ and |.
If, do, while, for, goto, switch etc. are not allowed, no macros, c++ functions (even compiler's intristic functions), &&, ||, ternary, and any other data types and structures, except for unsigned int.
这是我得到的,它可以工作,但它使用一个小循环,这是一个问题...
unsigned ReverseTetrads(unsigned x)
{
unsigned reversed = x&0xF;
while ((x >>= 4) != 0) {
reversed <<= 4;
reversed |= x&0xF;
}
return reversed;
}
示例:
0x12ABCD should be reversed to 0xDCBA21
这是我想出的:
unsigned ReverseTetrads(unsigned x)
{
unsigned
reversed = x&0xF,
offsets = 0;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed <<= 4;
x >>= 4;
offsets += !!x;
reversed |= x&0xF;
reversed >>= (7 - offsets) * 4;
return reversed;
}
完美适用于任何 unsigned int
。
首先使用标准位 hack 反转四分体,忽略前导零:交换顶部和底部 16 位,然后交换每 16 位中的顶部和底部字节,然后交换每个字节中的顶部和底部 nybble。
然后您可以通过检查底部 16 位、底部字节和底部 nybble 是否为零并适当移位来去除前导零(现在是尾随零)。我们可以相信 !x 在值为 0 时计算为 1,否则为 0。
unsigned int ReverseTetrads(unsigned int x)
{
// reverse tetrads ignoring leading zeros
x = (x << 16) | (x >> 16);
x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff);
x = ((x << 4) & 0xf0f0f0f0) | ((x >> 4) & 0x0f0f0f0f);
// get rid of the leading zeros (which are now trailing zeros)
x >>= !(x & 0x0000ffff) * 16;
x >>= !(x & 0x000000ff) * 8;
x >>= !(x & 0x0000000f) * 4;
return x;
}
根据问题,*
是允许的,但如果您认为它不算作位操作,那么您可以用 x >>= !(x & 0x0000ffff) << 4;
代替 x >>= !(x & 0x0000ffff) * 16;
等