假设我有一个递增的无符号整数序列C[i]
。随着它们的增加,它们可能会占据越来越多的位。我正在寻找一个有效的条件,纯粹基于序列C[i]
和C[i+1]
的两个连续元素(过去和未来的元素是不可观察的),它们将精确或近似地评估为真每次所需的位数增加。
条件的明显(但缓慢)选择是:
if (ceil(log(C[i+1])) > ceil(log(C[i]))) ...
同样可以使用特殊的cpu操作码来计算前导零位的数量(更好但仍然不是很好)。
我怀疑可能有一个很好的解决方案涉及一个表达式,只使用按位或按位并且值C[i+1]
和C[i]
。有什么想法吗?
答案 0 :(得分:16)
假设您的两个数字是x和y。如果它们具有相同的高阶位,则x ^ y小于x和y。否则,它高于两者中的一个。
所以
v = x^y
if (v > x || v > y) { ...one more bit... }
答案 1 :(得分:2)
我认为你只需要clz(C[i+1]) < clz(C[i])
其中clz
是一个函数,它返回前导零的数量(“计数前导零”)。一些CPU系列有一个指令(可能作为一个内在的可用)。如果没有,那么您必须自己动手(通常只需要几条指示) - 请参阅Hacker's Delight。
答案 2 :(得分:0)
当值大约溢出2时,位数会增加。那么一个简单的测试就是,这个值等于2的幂,减1?这可以通过询问:
来完成if ((C[i] & (C[i]+1))==0) ...
答案 3 :(得分:0)
鉴于(我认为这来自Hacker's Delight):
int hibit(unsigned int n) {
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n - (n >> 1);
}
您的条件只是hibit(C[i]) != hibit(C[i+1])
。
答案 4 :(得分:0)
BSR - 位扫描反转(386 +)
Usage: BSR dest,src
Modifies flags: ZF
Scans source operand for first bit set. Sets ZF if a bit is found
set and loads the destination with an index to first set bit. Clears
ZF is no bits are found set. BSF scans forward across bit pattern
(0-n) while BSR scans in reverse (n-0).
Clocks Size
Operands 808x 286 386 486 Bytes
reg,reg - - 10+3n 6-103 3
reg,mem - - 10+3n 7-104 3-7
reg32,reg32 - - 10+3n 6-103 3-7
reg32,mem32 - - 10+3n 7-104 3-7
你需要其中两个(在C [i]和C [i] +1上)和比较。
答案 5 :(得分:0)
Keith Randall的解决方案很好,但您可以使用以下代码保存一条xor指令,该代码在O(w + n)指令中处理整个序列,其中w是一个字中的位数,n是序列中的元素数量。如果序列很长,大多数迭代只涉及一次比较,避免一个xor指令。
这是通过跟踪已达到的两个最高功率来完成的,如下所示:
t = 1; // original setting
if (c[i + 1] >= t) {
do {
t <<= 1;
} while (c[i + 1] >= t); // watch for overflow
... // conditional code here
}
答案 6 :(得分:-1)
当值即将溢出2的幂时,位数会增加。 那么一个简单的测试就是:
while (C[i] >= (1<<number_of_bits)) then number_of_bits++;
如果你想要更快:
int number_of_bits = 1;
int two_to_number_of_bits = 1<<number_of_bits ;
... your code ....
while ( C[i]>=two_to_number_of_bits )
{ number_of_bits++;
two_to_number_of_bits = 1<<number_of_bits ;
}