仅使用位操纵来获得镜像的六角形

Reverse tetrads (nybbles) to get a mirrored hex using bit manipulations only

本文关键字:镜像 六角形 操纵      更新时间:2023-10-16

我有一个有趣的任务来帮助某人;在这里是:

写一个功能,以仅使用位操作,常数,〜!* - sizeof()<<>>&^ and |。

如果不允许使用,,对于goto,switch等。除了未签名的

这是我所拥有的,它有效,但是它使用了一个微小的循环,这是一个问题...

unsigned ReverseTetrads(unsigned x)
{
   unsigned reversed = x&0xF;
   while ((x >>= 4) != 0) {
      reversed <<= 4;
      reversed |= x&0xF;
   }
   return reversed;
}

示例:

0x12ABCD应将其转换为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

首先使用标准位黑手来扭转四分法,忽略领先的零:交换顶部和底部16位,然后在每个16位内交换顶部和底部字节每个字节内的底部nybble。

然后,您可以通过检查底部16位,底部字节和底部nybble是否为零并适当地转移来摆脱领先的零(现在正在落后零)。我们可以依靠以下事实:x评估为1的值为0,否则为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;等。