【问题标题】:Bitwise comparison按位比较
【发布时间】:2014-10-18 22:34:50
【问题描述】:

我有一个表示 8x8“位”块的数组

unsigned char plane[8]

我想要做的是水平循环通过这个“位”块 并计算之间发生变化的次数 10

当我提取一点时,它被存储在一个 unsigned char,所以基本上我想增加一个计数 当一个字符为非零而另一个字符为零时。

我有以下内容:

int getComplexity(unsigned char *plane) {
    int x, y, count = 0;
    unsigned char bit;

    for(x = 0; x < 8; x++) {
        for(y = 0; y < 8; y++) {
            if(y == 0) {
                bit = plane[x] & 1 << y;
                continue;
            }

        /*
        MISSING CODE
        */
        }
    }
}

对于缺少的代码,我可以这样做:

if( (bit && !(plane[x] & 1 << y)) || (!bit && (plane[x] & 1 << y)) ) {
    bit = plane[x] & 1 << y;
    count++;
}

但是,我真正想看看是否有一些 聪明的按位运算来代替这一步 有两个单独的测试。

【问题讨论】:

  • BitScanForward 内在可以为你做到这一点
  • 你可以做类似popcount(A ^ (A &lt;&lt; 1))的事情。不过,您可能需要小心边缘
  • 另一种选择:每个y 将字节旋转一位,如ideone.com/jfcSNk
  • ((x &amp;&amp; !y) || (!x &amp;&amp; y)) == (!x != !y).
  • 一种更有效的方法是预先计算一个表。当然,内在函数仍然更有效。

标签: c bit-manipulation


【解决方案1】:

这实际上只是一个 gcc 解决方案,因为 popcnt 内在函数不会在每个其他编译器上工作。

unsigned char plane[8];

static const uint64_t tmask = 0x8080808080808080UL;

uint64_t uplane = *(uint64_t *)plane; // pull the whole array into a single uint

return __builtin_popcnt( ~tmask & (uplane ^ (uplane >> 1) ) );

对于 x86,popcnt 指令直到 sse4.2 才真正实现(最近如此)。 此外,虽然这看起来依赖于字节顺序,但它并非如此,因为由于掩码,不允许任何单个字节进行交互。 它正在对内存的工作方式做出一些假设:\

顺便说一句,在“水平”方向上做同样的事情同样简单:

return __builtin_popcnt(0xFFFFFFFFFFFFFFUL & ( uplane ^ (uplane >> 8) ) );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    相关资源
    最近更新 更多