以下是我写的代码,在大的循环中效率还不是特别好,想有更好的办法。
第二个函数涉及多个整数,有无合适SSE指令可以直接用?
1 static int getFirstBit(int n)
2 {
3 if(n==-1)return -1;
4 unsigned int m = n^- 1;
5 int nbit = 0;
6 #define p(x,y) if(m & (((1<<x) - 1))<<x) m>>=x; else nbit+=x; y
7 p(16,p(8,p(4,p(2,p(1,return nbit)))));
8 #undef p
9 }
10 static int getFirstBit(int pn[], int bits)
11 {
12 int nIndex = bits/vBitsPerInt;
13 int nOffset = bits % vBitsPerInt;
14 int nbit = -1;
15 int ttl = 0;
16 int i = 0;
17 while(nbit==-1 && i<nIndex)
18 {
19 if(pn[i]!=-1)
20 nbit = getFirstBit(pn[i]);
21 else
22 ttl += vBitsPerInt;
23 i++;
24 }
25 if(nbit==-1 && nOffset)
26 {
27 int v = pn[nIndex] | (1<<(vBitsPerInt - nOffset)) - 1;
28 if(v!=-1) nbit = getFirstBit(v);
29 }
30 if(nbit==-1) return -1;
31 return nbit + ttl;
32 }
开始出现零的位置”是指二进制表示从左到右第一个0 。 任意位置是0,是指只要找到任意一位是零,输出这个位置就可以了。
"最开始出现零的位置,或者随便位置有零也可以"真的没讲清楚。“最开始出现零的位置”是指二进制表示从左到右第一个0还是从右到左? 随便位置有0也可以是什么意思? 任意位置是0,输出这个位置就可以了?
int n = 19999;
//对应二进制表示为 100111000011111
int zeroPosition = 0;
while (n & 1 != 0)
{
zeroPosition++;
n = n >> 1;
}
//右起第zeroPosition位是0
核心思想是用移位操作符,将n不断向右移位,直到能被2整除(也就是说最后一位变成0)为止。以上是C#代码。不过其他语言肯定也有移位操作符的。
是的, 最开始出现零的位置”是指二进制表示从左到右第一个0 。 任意位置是0,是指只要找到任意一位是零,输出这个位置就可以了。
@走在溪边: 看我修改之后的答案。
@水牛刀刀: 谢谢, 这样做程序比较简单,但平均需要循环16次。因为代码被调用的次数比较多,又在锁里面,希望能有更直接的方法。
@走在溪边: 平均循环16次你是怎么得出来的?从右边起找到0就停止了啊。
@水牛刀刀: 直接找到或者循环30多次才找到机会是均等的呀。
@走在溪边: 想了很久也没想出来。上面的可以稍微优化一下,把 n % 2 != 0 改成 n & 1 != 0,速度会稍微快一点,这是我能想到的最优解。如果你找到了更好的解法,留言告诉我。
@水牛刀刀: 晕倒, 386上直接有bsf指令, window上有_BitScanForward, _BitScanReverse函数, 应该是直接使用bsf指令。 觉得有这样的指令,却没有细查,一个不大不少的教训。
m = n^- 1;
然后算出m是2的多少整数次方,那第几位便是第一个0