请教大牛们一个算法问题

breakfisher 2013-11-19 11:35:44
给定一个二进制数data, 要取出对应mask_falg上值为1的位组成一个新数, 比如:

例1:
data : 10001
mask_flag 10101
这样结果就是取出data的1,3,5的数值为101,值为5

例2:
data : 10001
mask_flag 10111
这样结果就是取出data的1,2,3,5的数值为1001,值为9


有没有不需要循环, 直接通过位运算就可以得出结果的方法?
...全文
347 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-11-22
  • 打赏
  • 举报
回复
C++

//这个是 模仿 C++库函数写的
inline unsigned int countBitsHalfByte(unsigned char x){
            //  0 1 2 3 4 5 6 7 8 9 a b c d e f
    return "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4"[x];
}
inline unsigned int countBitsByte(unsigned char x){
    return countBitsHalfByte(x& 0xF) +countBitsHalfByte((x&0xF0)>>4);
}

template<typename intT >unsigned int countBits(intT x){
    int n=0;
    union{ intT d;unsigned char by[sizeof(x)];}v;
    v.d =x;
    for(int i = 0;i < sizeof(x); i++){
        n +=countBitsByte(v. by[ i ]);
    }
    return n;
}

int32_t tab_all_1[] =
       { 0,
         0x00000001,0x00000003,0x00000007,0x0000000f,0x0000001f,0x0000003f,0x0000007f,0x000000ff,
         0x000001ff,0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,0x00007fff,0x0000ffff,
         0x0001ffff,0x0003ffff,0x0007ffff,0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
         0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff,
       };
AnYidan 2013-11-21
  • 打赏
  • 举报
回复
某些 mcu 中有一个求前导零的指令
AnYidan 2013-11-21
  • 打赏
  • 举报
回复
引用 7 楼 breakfisher 的回复:
谢谢哈! 这个还是需要循环吧 [quote=引用 5 楼 AnYidan 的回复:]

int lowbit(int x) 
{
	return (x & (-x));
}
--网上的一个函数,可以返回 x 最低位是 0 还是 1 同时右移 data 和 mask_flag,当mask_flag的最低位是1时,记录data 的最低位并计算
[/quote] 只是一段合用的程序,mcu 中有一个求前导零的指令,对数字的前导零进行计数,并将结果返回,虽然可能仍需用到循环,但应该可以大幅提高效率
lm_whales 2013-11-21
  • 打赏
  • 举报
回复
引用 6 楼 breakfisher 的回复:
恩,谢谢! 考虑过查表, 表要是二维的, 现在只需要8位, 但是担心后面位数多了不好扩展 [quote=引用 4 楼 lm_whales 的回复:] 对于你这个只有5位或者8位的,可以生成一个表,然后查表。 如果位数较多,就不好使用。
[/quote] 想到一个查表方法,不一定比移位逐位处理快 位数比较多,表里可以同时有1的个数和最后的结果值 然后合并每个字节的结果。
breakfisher 2013-11-20
  • 打赏
  • 举报
回复
谢谢哈! 这个还是需要循环吧
引用 5 楼 AnYidan 的回复:

int lowbit(int x) 
{
	return (x & (-x));
}
--网上的一个函数,可以返回 x 最低位是 0 还是 1 同时右移 data 和 mask_flag,当mask_flag的最低位是1时,记录data 的最低位并计算
breakfisher 2013-11-20
  • 打赏
  • 举报
回复
恩,谢谢! 考虑过查表, 表要是二维的, 现在只需要8位, 但是担心后面位数多了不好扩展
引用 4 楼 lm_whales 的回复:
对于你这个只有5位或者8位的,可以生成一个表,然后查表。 如果位数较多,就不好使用。
赵4老师 2013-11-20
  • 打赏
  • 举报
回复
这个用嵌入汇编实现即可。
breakfisher 2013-11-19
  • 打赏
  • 举报
回复
一楼这个不对, 发现例子里面漏了一个字, 更正一下 例1: data : 10001 mask_flag 10101 这样结果就是取出data的1,3,5位的数值为101,值为5 例2: data : 10001 mask_flag 10111 这样结果就是取出data的1,2,3,5位的数值为1001,值为9
worldy 2013-11-19
  • 打赏
  • 举报
回复
n=data & mask_flag;// 10001 //mask_flag 10101
AnYidan 2013-11-19
  • 打赏
  • 举报
回复

int lowbit(int x) 
{
	return (x & (-x));
}
--网上的一个函数,可以返回 x 最低位是 0 还是 1 同时右移 data 和 mask_flag,当mask_flag的最低位是1时,记录data 的最低位并计算
lm_whales 2013-11-19
  • 打赏
  • 举报
回复
对于你这个只有5位或者8位的,可以生成一个表,然后查表。 如果位数较多,就不好使用。
图灵狗 2013-11-19
  • 打赏
  • 举报
回复
必须用到循环:

int extract(int data, int mask)
{
	int value = 0;
	int i;
	int j = 0;

	for(i = 0; i < 32; i++)
	{
		if(mask & (1 << i))
		{
			if(data & (1 << i))
				value |= 1 << j;
			j++;
		}
	}

	return value;
}
引用 楼主 breakfisher 的回复:
给定一个二进制数data, 要取出对应mask_falg上值为1的位组成一个新数, 比如: 例1: data : 10001 mask_flag 10101 这样结果就是取出data的1,3,5的数值为101,值为5 例2: data : 10001 mask_flag 10111 这样结果就是取出data的1,2,3,5的数值为1001,值为9 有没有不需要循环, 直接通过位运算就可以得出结果的方法?

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧