扩展一下saluce的答案:
位测试
您可以构建测试模式,因此您不需要单独检查每一位(测试整数比测试一位更快,尤其是一次测试整数就像好):
testOnes = 128 & 64 // the bits we want to be 1
testZeros = ~(8 & 4) // the bits we want to be 0, inverted
然后以这种方式执行测试:
if (!(~(x & testOnes) & testOnes) &&
!(~(~x | testZeros))) {
/* match! */
}
逻辑解释:
首先,在两者中testOnes
,testZeros
您都将感兴趣的位设置为 1,其余设置为 0。
testOnes testZeros
11000000 11110011
然后x & testOnes
将我们不想测试的所有位清零(注意和之间的区别&
:&&
按位&
执行逻辑AND
运算,而&&
对AND
整数执行逻辑运算)。
testOnes
11000000
x x & testOnes
11110000 11000000
11000010 11000000
01010100 01000000
现在我们测试为 1 的位最多可以是 1,但我们不知道它们是否都是 1:通过反转结果 ( ~(x & testOnes)
),我们得到所有我们不关心的数字是 1 和位我们要测试的是 0(如果它们是 1)或 1(如果它们是 0)。
testOnes
11000000
x ~(x & testOnes)
11110000 00111111
11000010 00111111
01010100 10111111
通过AND
对它进行按位运算,testOnes
如果感兴趣的位在 中全为 1,则我们得到 0 x
,否则为非零。
testOnes
11000000
x ~(x & testOnes) & testOnes
11110000 00000000
11000010 00000000
01010100 10000000
在这一点上,我们有: 0 如果我们想要测试 1 的所有位实际上都是 1,否则为非 0,因此我们执行一个逻辑NOT
来将 0 变为true
,将非 0 变为false
。
x !(~(x & testOnes) & testOnes)
11110000 true
11000010 true
01010100 false
零位的测试类似,但我们需要使用按位- OR
( |
),而不是按位- AND
( &
)。首先,我们翻转x
,因此应该为 0 的位变为应该为 1,然后OR
-ing 将所有不感兴趣的位变为 1,同时保留其余位;所以在这一点上,如果应该是 0 的位x
确实为 0,则我们有全 1,否则,我们将结果再次翻转以在第一种情况下得到 0,在第二种情况下得到非 0 . 然后我们应用逻辑NOT
(!
)将结果转换为true
(第一种情况)或false
(第二种情况)。
testZeros
11110011
x ~x ~x | testZeros ~(~x | testZeros) !(~(~x | testZeros))
11110000 00001111 11111111 00000000 true
11000010 00111101 11111111 00000000 true
01010100 10101011 11111011 00000100 false
注意:您需要意识到我们为每个测试执行了 4 次操作,所以总共 8 次。根据您要测试的位数,这可能仍然少于单独检查每个位。
算术测试
测试相等/差异很容易:XOR
测试的数字 - 如果所有位都相等(因此数字相等),则为 0,如果至少有一位不同(因此数字不同),则为非 0。(应用NOT
将相等的测试结果true
,差异变为false
。)
然而,为了测试不等式,你大部分时间都不走运,至少它适用于逻辑运算。您是正确的,可以通过逻辑运算(按位AND
并测试 0)来检查 2 的幂(例如,您的问题中的 16),但是对于不是 2 的幂的数字,情况并非如此简单的。举个例子,让我们测试一下x>5
:pattern 是 00000101,那么如何测试呢?如果它的前 5 个最高有效位为 1,则该数字更大,但 6 (00000110) 也更大,前 5 个位均为 0。
您可以做的最好的事情是测试该数字是否至少是该数字中最高 2 的幂的两倍(在上面的示例中为 5 的 4)。如果是,那么它比原来的大;否则,它必须至少与数字中的最高 2 次方一样多,然后对不太重要的位执行相同的测试。如您所见,操作数是根据测试数中 1 位的数量动态变化的。
链接位
这XOR
是你的朋友:XOR
如果两个位相同,则为 0,否则为 1。
我不知道执行测试的简单方法,但以下算法应该会有所帮助:
假设您需要 bits b1
, ...,bn
相同(全 1 或全 0),然后将所有其他位清零(参见AND
上面的逻辑-),然后隔离测试模式中的每个位,然后将它们排列在相同的位置(为方便起见,我们将其设为最低有效位)。然后XOR
-ing其中两个然后XOR
-ing第三个结果等。将在每个奇数步产生一个偶数,如果原始数字中的位相同,则在每个偶数步产生奇数。您需要在每一步都进行测试,因为对于大量要测试的链接位,仅测试最终结果可能是不正确的。
testLinks
00110000
x x & testLinks
11110000 00110000
11000010 00000000
01010100 00010000
x x's bits isolated isolated bits shifted
11110000 00100000 00000001
00010000 00000001
11000010 00000000 00000000
00000000 00000000
01010100 00000000 00000000
00010000 00000001
x x's bits XOR'd result
11110000 00000000 true (1st round, even result)
11000010 00000000 true (1st round, even result)
01010100 00000001 false (1st round, odd result)
注意:在类 C 语言中,XOR
运算符是^
.
注意:如何将位对齐到相同的位置?位移。Shift-left ( <<
) 将所有位向左移动,“丢失”最高有效位并将 0“引入”最低有效位,实质上是将数字乘以 2;右移>>
( .