bitParity - 查找整数中的奇数位

Posted

技术标签:

【中文标题】bitParity - 查找整数中的奇数位【英文标题】:bitParity - Finding odd number of bits in an integer 【发布时间】:2012-02-26 08:15:31 【问题描述】:

我必须创建一个函数bitParity(int x),它接受一个整数并返回1,如果x的位形式有奇数个0,否则返回0

例如:bitParity(5) = 0, bitParity(7) = 1

但是,这很困难,因为我只能在这个问题上使用位运算符(! ˜ & ˆ | + << >> 是唯一合法的)。这意味着,没有循环、if-then 或任何类似的东西。可以使用常量。

到目前为止,我所拥有的不起作用,但我认为我应该将整数 1684 的位移位,并将剩余的整数 XOR 移位。

谁能给点建议?谢谢。

【问题讨论】:

您应该始终检查按位示例的第一个位置是graphics.stanford.edu/~seander/bithacks.html#ParityLookupTable 查找表是最好的方法。 256 字节的存储空间是一个很小的代价。如果您使用 32 位整数,只需从表中读取 4 次。 除了@Joe 提到的,你也可以参考catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know。这有一些我觉得很有用的原始技巧。 看看这个***.com/a/21618038/2672154 【参考方案1】:

对于 32 位数字:

function bitParity(int x) 
   x ^= x >> 16;
   x ^= x >> 8;
   x ^= x >> 4;
   x &= 0xf;
   return (0x6996 >> x) & 1;

注意* 0x6996 表示数字 1、2、4、7、8、11、13 和 14 的位向量。所有 4 位值都可以用一个奇数位。在 0x6996 中,如果它在向量中的位置对应于(1、2、4、7、8、11、13 或 14),则设置一个位。

这就是为什么 (0x6996 >> x) & 1 有意义的原因,在移位 x 之后,如果 x 等于位向量中的任何值,则此表达式只会返回 1,这意味着奇数位已设置。

【讨论】:

魔术解释:x ^= x>>16之后,低16位与原来的奇偶校验相同。再多两行,你就有 4 位具有正确的奇偶校验。在&= 之后,您有一个介于 0 和 15 之间的数字(具有正确的奇偶校验)。 0x6996 用作查找表 - 对于 0 到 15 之间的每个数字,您可以选择其中一个位。 @Joe - 正如 ugoren 解释的那样,0x6996 是一个很小的查找表;) 这只是一种超高效的方法,需要 很多 的理解。 ..但它有效。【参考方案2】:

这可以通过循环正确解决。但这里有一种不用的方法。

x = (x & 0x0000FFFF) ^ (x >> 16)
x = (x & 0x000000FF) ^ (x >> 8)
x = (x & 0x0000000F) ^ (x >> 4)
x = (x & 0x00000003) ^ (x >> 2)
x = (x & 0x00000001) ^ (x >> 1)

编辑:我不需要 &。更好的版本:

x ^= x >> 16
x ^= x >> 8
x ^= x >> 4
x ^= x >> 2
x ^= x >> 1
x &= 1;

【讨论】:

非常感谢!我非常接近,但错过了最后的 x&1。你能告诉我你是如何得出这个结论的吗?谢谢。 我不确定。我正在考虑它,我有一个脑电波。我的第一个想法是对所有位进行异或运算,一次一个。但这将是丑陋的。通过这种方式,我将其想象为将数字反复折叠到自身上。【参考方案3】:

这是我在完成学士论文时使用的函数之一 ;)

/** Calculates number of bits in unsigned char
 * @brief Bit count
 * @param input to be checked
 * @return int 0-8
 */
int bitCount( unsigned char input)

    static unsigned char count[] =  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 ;
    return (int)(
            count[ input & 0x0f] +
            count[ (input >> 4) & 0x0f]
    );

所以 4B 整数的总数为:

int bytes = bitCount( (unsigned char)((number >> 0)&255))
            + bitCount( (unsigned char)((number >> 8)&255))
            + bitCount( (unsigned char)((number >> 16)&255))
            + bitCount( (unsigned char)((number >> 24)&255));

和奇偶校验:

 return bytes%2;
 return bytes&1; // if you preffer

我一直想重用这些代码 :)

编辑: 正如您可能注意到的那样,unsigned char (8b) 可以分成 2 块,每块 4b 长,这意味着 16 个值易于存储和重用。所以你从整数中取出第一个 8b,将它们分成两部分。确保它们都在间隔<0,15> 中,并且直接获取位数。重复:)

【讨论】:

请看约束。

以上是关于bitParity - 查找整数中的奇数位的主要内容,如果未能解决你的问题,请参考以下文章

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

打印整数二进制的奇数位和偶数位

java编写将一串字符串中的奇数位提出来相加并且偶数位每个数相加

js怎么取一个数组中的奇数位元素或者偶数位元素

使用按位运算符查找每个偶数位是不是设置为 0