是否可以从左数开始计算整数中的连续1? 所以:从最高位开始的连续设置位的总数。
仅使用:
! ~ & ^ | + << >>
-1
= 0xFFFFFFFF
将返回32
0xFFF0F0F0
将返回12(FFF = 111111111111)
不幸的是没有循环。
可以假设机器:
使用2s补码,32位整数表示。
以算术方式执行右移。
将整数移位更多时,行为不可预测 比单词大小。
我被禁止:
使用任何控制结构,例如if,do,while,for,switch等。
定义或使用任何宏。
在此文件中定义任何其他功能。
调用任何函数。
使用任何其他操作,例如&amp;&amp;,||, - 或?:
使用任何形式的铸造。
使用除int之外的任何数据类型。这意味着你 不能使用数组,结构或联合。
我看过了 Finding consecutive bit string of 1 or 0 它使用循环,我不能使用。我甚至不知道从哪里开始。
(是的,这是一项任务,但我只是要求那些熟练的人帮忙。我已经做了很多我需要做的事情,但是这个不会起作用。)< / p>
(对于那些仅仅因为它是为了学校而贬低的人: 常问问题: 1一个特定的编程问题,检查 2但是,如果你的动机是“我希望别人向我解释______”,那么你可能就好了。)
答案 0 :(得分:2)
你在这里。函数参数可以是有符号或无符号的。 alg独立于签名。
int leftmost_ones(int x)
{
x = ~x;
x = x | x >> 1 | x >> 2 | x >> 3 | x >> 4 | x >> 5 | x >> 6 | x >> 7 |
x >> 8 | x >> 9 | x >> 10 | x >> 11 | x >> 12 | x >> 13 | x >> 14 |
x >> 15 | x >> 16 | x >> 17 | x >> 18 | x >> 19 | x >> 20 | x >> 21 |
x >> 22 | x >> 23 | x >> 24 | x >> 25 | x >> 26 | x >> 27 | x >> 28 |
x >> 29 | x >> 30 | x >> 31;
x = ~x;
return (x & 1) + (x >> 1 & 1) + (x >> 2 & 1) + (x >> 3 & 1) + (x >> 4 & 1) +
(x >> 5 & 1) + (x >> 6 & 1) + (x >> 7 & 1) + (x >> 8 & 1) + (x >> 9 & 1) +
(x >> 10 & 1) + (x >> 11 & 1) + (x >> 12 & 1) + (x >> 13 & 1) + (x >> 14 & 1) +
(x >> 15 & 1) + (x >> 16 & 1) + (x >> 17 & 1) + (x >> 18 & 1) + (x >> 19 & 1) +
(x >> 20 & 1) + (x >> 21 & 1) + (x >> 22 & 1) + (x >> 23 & 1) + (x >> 24 & 1) +
(x >> 25 & 1) + (x >> 26 & 1) + (x >> 27 & 1) + (x >> 28 & 1) + (x >> 29 & 1) +
(x >> 30 & 1) + (x >> 31 & 1);
}
具有一些优化的版本:
int leftmost_ones(int x)
{
x = ~x;
x |= x >> 16;
x |= x >> 8;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
x = ~x;
return (x & 1) + (x >> 1 & 1) + (x >> 2 & 1) + (x >> 3 & 1) + (x >> 4 & 1) +
(x >> 5 & 1) + (x >> 6 & 1) + (x >> 7 & 1) + (x >> 8 & 1) + (x >> 9 & 1) +
(x >> 10 & 1) + (x >> 11 & 1) + (x >> 12 & 1) + (x >> 13 & 1) + (x >> 14 & 1) +
(x >> 15 & 1) + (x >> 16 & 1) + (x >> 17 & 1) + (x >> 18 & 1) + (x >> 19 & 1) +
(x >> 20 & 1) + (x >> 21 & 1) + (x >> 22 & 1) + (x >> 23 & 1) + (x >> 24 & 1) +
(x >> 25 & 1) + (x >> 26 & 1) + (x >> 27 & 1) + (x >> 28 & 1) + (x >> 29 & 1) +
(x >> 30 & 1) + (x >> 31 & 1);
}
答案 1 :(得分:1)
你能使用循环吗?
int mask = 0x80000000;
int count = 0;
while (number & mask) {
count += 1;
mask >>= 1;
}
答案 2 :(得分:1)
你可以这样做:
int result = clz(~x);
即。反转所有位,然后计算前导零。
clz
返回前导零位数(通常也称为ffs
或nlz
) - 有关实施详情,请参阅此处:http://en.wikipedia.org/wiki/Find_first_set#Algorithms
答案 3 :(得分:1)
我认为这是可行的,基本上是展开典型的循环并且通常很烦人。
这个怎么样:当且仅当答案为1时,表达式为1?我提供:
const int ok1 = !((number & 0xc0000000) - 0x800000000);
!
和减法可以解决有人打破我们键盘上的==
键的问题。
然后,当且仅当anwer为2时,表达式为1:
const int ok2 = !((number & 0xe0000000) - 0xc0000000);
如果你继续形成这些,最后的答案是他们的总和:
const int answer = ok1 + ok2 + ... + ok32;
顺便说一下,我似乎不记得在我上学的时候被给予这些奇怪的限制任务,我想时间已经改变了。 :)
答案 4 :(得分:0)
int count_consecutive_bits(unsigned int x) {
int res = 0;
while (x & 0x80000000) { ++res; x <<= 1; }
return res;
}