加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 将大小<= N到1的连续0位的所有组翻转

发布时间:2020-12-16 05:42:37 所属栏目:百科 来源:网络整理
导读:说我有一个无符号的M位整数(其中M是8,16,32,64之一),其中有0位的各种运行: … 111 000 11 00 1 0000 1 0 1 00000 111 … 给定一个N,其中0 = N = M,我想填充大小为 = N的整数的0的所有组.所以如果对于上述整数,我们给出N = 3,结果将是: … 111 111 11 11 1
说我有一个无符号的M位整数(其中M是8,16,32,64之一),其中有0位的各种运行:

… 111 000 11 00 1 0000 1 0 1 00000 111 …

给定一个N,其中0 <= N <= M,我想填充大小为< = N的整数的0的所有组.所以如果对于上述整数,我们给出N = 3,结果将是: … 111 111 11 11 1 0000 1 1 1 00000 111 … 请注意,4组和5组零没有翻转,因为它们的大小为> 3.

如何在C/C++中编写高效的实现方法?我假设有一些聪明的一点可以做,但我不知道从哪里开始.我已经看到用来传播一个位模式的乘法,但是没有这种可变长度检查.同样的原因,查找表看起来很痛苦.一个很好的减法1可以翻转一些位,但是找出什么减去看起来很棘手.

编辑:要清楚,虽然M在编译时固定,N可以在运行时变化.

解决方法

x = ~x;
for (j = 1; j <= N/2; j *= 2) x &= (x >> j);
x &= (x >> (N - j + 1));
for (j = 1; j <= N/2; j *= 2) x |= (x << j);
x |= (x << (N - j + 1));
x = ~x;

与R ..的解决方案相同的想法,但有一点优化.

为了优化更多,可以消除第二个循环:

t = ~x;
m = x & (t << 1);
for (j = 1; j <= N/2; j *= 2) t &= (t >> j);
t &= (t >> (N - j + 1));
t |= ((m - t) & ~m);
x = ~t;

这里唯一剩下的循环移除位组(与前面的变体完全相同),而不是第二个循环,使用简单的按位技术来恢复长于N个组.

实施例(N = 4):

input string  110000100000011
inverted one  001111022222100
loop iter. 1  000111002222200
loop iter. 2  000001000011100
one more iter 000000000001100

第一个循环迭代工作正常,因为每个位组前面至少有一个零位.因此,我们在每个位组之前至少有两个零位.因此,可以在第二次循环迭代时一次移位两位.同样的原因,第三次循环迭代可能会一次移位4位,但是这个例子不需要大于2位的位移.由于循环已经将位组移位了3位,我们必须将它们移位N-3 = 1位以上(由循环后的下一行完成).

现在较小的位组消失了,但较大的位组由一对位表示.为了重建剩余的组,可以使用第二循环:

starting with 000000000001100
loop iter. 1  000000000011100
loop iter. 2  000000002222200
one more iter 000000022222100
result        222221100000011

或者代替第二个循环,我们可能会使用一个按位的技巧:

m             010000100000000
t             000000000001100
m-t           010000011110100
(m-t) & ~m    000000011110100
t|((m-t)&~m)  000000022222100
result        222221100000011

m标志着每个组的开始. m-t恢复所有偏移位.下一个操作会清除m的未使用位.需要一个操作来将恢复的位与移位循环之后剩余的位组合.

基准测试结果(AMD K8,GCC 4.6.3 -O2),秒数:

N one_loop two_loops unoptimized
1     3.9     4.2       3.3
2     4.6     6.2       5.2
3     4.6     6.2       7.1
4     5.6     7.9       8.9
5     5.6     7.9      11.3
6     5.6     7.9      13.3
15    6.7    10.0      46.6

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读