如果符合以下条件,我必须检查一个数字:
我编写了一个代码,用于检查实际问题的这些条件(检查数据文件的完整性)。
它可以毫无问题地工作,除了时间紧迫之外什么都没有,但我是一个古老的比特狂热的怪物并喜欢这样的谜题,所以我试图想出一个更聪明的方法来检查单一 - 比特流。
字符串被零包围的情况很容易,但是那个不能处理特殊情况。
欢迎任何想法,二元黑客和部分解决方案!
为了使我的要求更清楚一些例子:以下数字符合我的标准:
0x80000000
0x00000001
0xff000000
0x000000ff
0xffffffff
0x000ff000
以下数字不会(因为它们有多个连续的字符串):
0xf00000f <- one-bit streams should not wrap-around at 2^n
0x0001700 <- a trivial example.
0x0000000 <- no one bit at all.
答案 0 :(得分:3)
bool isOK(uint val) {
while (val != 0 && (val & 1u) == 0) val >>= 1;
if (val == 0) return false;
while (val != 0 && (val & 1u) == 1) val >>= 1;
return val == 0;
}
; x86 assembly
mov eax, THE_NUMBER ; store the number in eax
bsf ecx, eax
jz .notok
mov edi, 1
shl edi, cl
mov esi, eax
add esi, edi
test esi, eax
jnz .notok
mov eax, 1
jmp .end
.notok:
mov eax, 0
.end: ; eax = 1 if satisfies the criteria, otherwise it's 0
答案 1 :(得分:3)
这应该做你想要的。
if(i == 0)
return false;
while(i % 2 == 0) {
i = i / 2;
}
return (i & (i + 1)) == 0;
答案 2 :(得分:2)
我在方法hasInsetZero中解决了与http://smallissimo.blogspot.fr/2012/04/meteor-contest-part-3-reducing.html几乎相同的问题:(并使用了其他几个技巧)
hasInsetZero: aMask
| allOnes |
allOnes := aMask bitOr: aMask - 1.
^(allOnes bitAnd: allOnes + 1) > 0
它是Smalltalk代码,但是用C语言翻译(我们需要否定并关注0),那就是:
int all_set_bits_are_consecutive( x )
/* return non zero if at least one bit is set, and all set bits are consecutives */
{
int y = x | (x-1);
return x && (! (y & (y+1)));
}
答案 3 :(得分:1)
假设您想要快速,基本算法将是:
所有这些操作都是O(1)或O(log(整数位宽)),如下所示:
unsigned int lowest_power_of_2(unsigned int value)
{ return value & -value; }
unsigned int count_bits_set(unsigned int value)
{ /* see counting bits set in parallel */ }
unsigned int lowest_bit_set_or_overflow_if_zero(unsigned int value)
{ return count_bits_set(lowest_power_of_2(value) - 1); }
unsigned int is_zero_or_power_of_2(unsigned int value)
{ return value && (value & (value - 1))==0; }
bool magic_function(unsigned in value)
{ return is_zero_or_power_of_2((value >> (lowest_bit_set_or_overflow_if_zero(lowest_power_of_2(value)))) + 1); }
编辑:更新的最终操作占0,但是OP的算法要快得多,因为它都是常量操作(尽管溢出会占用PITA)。
MSN
答案 4 :(得分:1)
我会使用bsr和bsf来确定数字中设置的最小和最大位数。从那里,创建一个满足标准的有效数字。将已知有效数字与实际数字进行比较以获得相等性。没有循环,只有一个比较。
伪码:
min_bit = bsf(number);
max_bit = bsr(number);
valid_number = ~(-1 << (max_bit - min_bit) ) << min_bit;
return ( number == valid_number );
答案 5 :(得分:1)
我正在进行中的版本。不作为答案,只是为了提供更多的想法并记录我当前的方法:
int IsSingleBitStream (unsigned int a)
{
// isolate lowest bit:
unsigned int lowest_bit = a & (a-1);
// add lowest bit to number. If our number is a single bit string, this will
// result in an integer with only a single bit set because the addition will
// propagate up the the highest bit. We ought to end up with a power of two.
a += lowest_bit;
// check if result is a power of two:
return (!a || !(a & (a - 1)));
}
如果以下行:
,则此代码无效a + = lowest_bit
溢出。另外,我不确定如果有多个位字段,我的“隔离单位”代码是否有效。
答案 6 :(得分:0)
N位整数有(N^2 - N) / 2
种可能性(32位为496)。
您可以使用查找表。