这个问题有啥好的位运算写法?

FancyMouse Microsoft SDE  2013-10-14 09:41:14
先写一个我的naive版本:

uint64 transform(uint64 value, uint64 mask)
{
int c = 0;
uint64 result = 0;
for(int i=0, c=0;i<64;i++)
if(mask & (1ull<<i))
result |= ((value>>i) & 1)<<c++;
return result;
}

也就是说,mask提供需要提取的bit掩码,然后把value里掩码出来的bit给压缩到低k位里,k是mask里1的个数。
一个例子是:value: 110011, mask: 010111,那么返回1011
naive的写法人人会写。我的问题是,这个有啥更好的写法吗?比如可以像popcnt一样用log(n)次迭代来代替这里的线性迭代。我不知道这里能不能做类似的事情。
...全文
270 点赞 收藏 6
写回复
6 条回复
lunat 2013年11月02日
这个可以考虑一下局部查表法。 uint8_t values[65536]; uint8_t counts[256] for (int i = 0; i < 256; i++) for (int j = 0; j < 256; j++) values[(i << 8) | j] = transform8(i, j);//transform8:8位版本的transform
回复 点赞
lm_whales 2013年11月02日
最后一个是 x = (x & 0x000000ffff) + ((x& 0xffff0000) > 16);
回复 点赞
lm_whales 2013年11月02日
统计1的个数 写个 32Bits的 x = (x & 0x55555555) + ((x& 0xaaaaaaaa) > 1); x = (x & 0x33333333) + ((x& 0xcccccccc) > 2); x = (x & 0x0f0f0f0f) + ((x& 0xf0f0f0f0) > 4); x = (x & 0x0000ff00ff) + ((x& 0xff00ff00) > 8); x = (x & 0x000000ffff) + ((x& 0xffff0000) > 8);
回复 点赞
赵4老师 2013年10月14日
profiler
回复 点赞
图灵狗 2013年10月14日
这个写法效率已经相当的高,只能稍作修改:

uint64 transform2(uint64 value, uint64 mask)
{
	uint64 result = 0;
	uint64 bm = 1;
	int c = 0;
  
	for(int i = 0; i < 64; i++)
	{
    		if(mask & bm) result |= ((value >> i) & 1) << c++;
		bm <<= 1;
	}

	return result;
}
引用 楼主 FancyMouse 的回复:
先写一个我的naive版本:

uint64 transform(uint64 value, uint64 mask)
{
  int c = 0;
  uint64 result = 0;
  for(int i=0, c=0;i<64;i++)
    if(mask & (1ull<<i))
      result |= ((value>>i) & 1)<<c++;
  return result;
}
也就是说,mask提供需要提取的bit掩码,然后把value里掩码出来的bit给压缩到低k位里,k是mask里1的个数。 一个例子是:value: 110011, mask: 010111,那么返回1011 naive的写法人人会写。我的问题是,这个有啥更好的写法吗?比如可以像popcnt一样用log(n)次迭代来代替这里的线性迭代。我不知道这里能不能做类似的事情。
回复 点赞
dianyancao 2013年10月14日
删除数组中的几个指定元素,最坏情况下应该是O(n)
回复 点赞
发动态
发帖子
其它技术问题
创建于2007-09-28

3080

社区成员

9102

社区内容

C/C++ 其它技术问题
社区公告
暂无公告