重新开张 && two pieces of fascinating code

本文介绍了两种高效的位运算技巧:bit_reverse用于二进制位反序排列,count_ones用于计算二进制位1的个数。这两种技巧通过巧妙的位操作实现了高效计算,相较于常规算法具有更高的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写下这个题目,我的脸皮红得在发烧。我知道我很懒,但是远远低于Blog更新的平均周期仍然使我感到羞愧。然后是我在文章统计里看到了这个:

文章标题页面/聚合访问
英文版WindowsXP下中文名Chm文件无法打开的解决方法1662 /15
呵呵,发现了一个破解NTFS加密文件夹的另类方法4273 /14

两篇奇技淫巧文章占去了我一半的访问量,让我十分怀疑自己是否退化到了高中时的水平(那个时候最为痴迷的杂志是《电脑爱好者》)。因此,我想我应该写点符合一名CS的学生身份的东西。最近看了些面试题,有些东西还值得记录下来,如果我没有再次半途而废,这个系列会继续下去~~

--

先贴两段代码:

unsigned  int  bit_reverse(unsigned  int  n)
{
       n 
= ((n >> 1& 0x55555555| ((n << 1& 0xaaaaaaaa);
       n 
= ((n >> 2& 0x33333333| ((n << 2& 0xcccccccc);
       n 
= ((n >> 4& 0x0f0f0f0f| ((n << 4& 0xf0f0f0f0);
       n 
= ((n >> 8& 0x00ff00ff| ((n << 8& 0xff00ff00);
       n 
= ((n >> 16& 0x0000ffff| ((n << 16& 0xffff0000);
 
       
return n;
}

 
int  count_ones( int  n)
{
       n 
= (n & 0x55555555+ ((n & 0xaaaaaaaa>> 1);
       n 
= (n & 0x33333333+ ((n & 0xcccccccc>> 2);
       n 
= (n & 0x0f0f0f0f+ ((n & 0xf0f0f0f0>> 4);
       n 
= (n & 0x00ff00ff+ ((n & 0xff00ff00>> 8);
       n 
= (n & 0x0000ffff+ ((n & 0xffff0000>> 16);
 
       
return n;
}

 第一次看到是在C PUZZLES, Some interesting C problems,完全不懂它是在做什么,从函数名称上推断,bit_reverse是将一个unsigned int的二进制位反序排列,count_ones是计算一个unsigned int中二进制位1出现的次数。运行一下,的确结果是对的!今天在这里看到一贴回复,又演算了一下,方才明白其中的奥妙。

首先看bit_reverse的一个使用8bit的位串的简化示例,假定从左向右为每个位编号为1 2 3 4 5 6 7 8,

第一步:

((n >> 1) & 0x55) 即 (n >> 1) & 0101,0101),将位串上奇数位右移到偶数位上,得到0 1 0 3 0 5 0 7

((n << 1) & 0xaa) 即 ((n << 1) & 1010,1010),将位串上偶数位左移到奇数位上,得到2 0 4 0 6 0 8 0

两者相与,结果即得到奇数位和偶数位相互交换的位串:1 2 3 4 5 6 7 8 => 2 1 4 3 6 5 8 7

第二步:

分别将相邻的4位编为一组,左侧与右侧相互交换:2 1 4 3 6 5 8 7 => 4 3 2 1 8 7 6 5

第三步:

分别将相邻的8位编为一组,左侧与右侧相互交换:4 3 2 1 8 7 6 5 => 8 7 6 5 4 3 2 1.  ~End~

这段代码像是杂耍一样就完成工作了,呵呵。事实上,在Programming Pearls里Chapter 2里提到的字符串旋转的算法与此有异曲同工之妙。效率O(logn),比起阳春的O(n)算法要高得多。

再来看count_ones,依然使用8bit的位串的简化示例,这次假定位串值位1001,0110

第一步,将相邻的2位编为一组:

(n & 0x55) 即 (n & 0101,0101) = 0001,0100:计算出每一组中左侧位上1的个数,并保存在结果中该组对应的位置上;

((n & 0xaa) >> 1) 即 (n & 1010,1010) = 0100,0001:计算出每一组中右侧位上1的个数,并保存在结果中该组对应的位置上;

两者相加,得到该组中1的个数,并保存在结果中该组对应的位置上;

第二步,将相邻的4位编为一组,根据第一步中的算法,计算每组中1的个数,并保存在结果中该组对应的位置上:

(n & 0x33) + ((n & 0xcc) >> 2) 即 0001,0001 + 0001,0001 即 0010,0010;

第三步,将相邻的8位编为一组,根据第一步中的算法,计算每组中1的个数,并保存在结果中该组对应的位置上:

(n & 0x0f) + ((n & 0xf0) >> 4) 即 0000,0010 + 0000,0010 即 0000,0100(二进制4).  ~End~

如果上个算法像是杂耍,那这个算法就像是魔术了:-) (当然还有更加惊为天人鬼斧神工的,看Quake3中的快速平方根算法)。对于一般情况,这个算法的复杂度也是O(logn),相对于阳春的O(n)算法当然要高。但是在某些情况下,如果只有很少的位为1(考虑常见的标志位),那么还有下面的代码:  

int  CountBits(unsigned  int  x)
{
    
int count=0;
    
while(x)
    
{
        count
++;
        x 
= x&(x-1);
    }

    
return count;
}

 How does it work? Try to figure it out:-)

这只是关于位运算一点小trick,茶余饭后娱乐一下,搞嵌入式的大牛们就不必费心看过来了。有自虐倾向者请继续看向Algorithms for Programmers里的Chapter 1.

Certainly, I can write a small essay of 1000 words about Yunnan province of China. Yunnan is one of the most beautiful provinces in China, located in the southwestern part of the country. It is surrounded by mountains and is known for its diverse topography and natural beauty. The province is home to 25 different ethnic minority groups, which gives it a rich cultural heritage that is unique to the region. Yunnan has a rich history, and there are many fascinating historical sites to visit throughout the province. One of the most famous historical sites is the ancient city of Dali, which dates back to the 14th century. The city is surrounded by the beautiful Cangshan Mountains and is known for its traditional architecture and unique culture. Another must-visit city in Yunnan is Lijiang, which is a UNESCO World Heritage Site. The old town of Lijiang is well-preserved and is a beautiful example of traditional Naxi architecture. The city is also famous for its Jade Dragon Snow Mountain, which is one of the most magnificent peaks in the world. In addition, Yunnan has some of the most beautiful natural landscapes in China, with towering mountains, deep gorges, and clear lakes. The Three Parallel Rivers of Yunnan Protected Areas is a UNESCO World Heritage Site that encompasses the area where the Jinsha, Lancang, and Nujiang rivers flow parallel to each other for over 300 kilometers. This region features spectacular natural scenery, including the deep canyons, majestic waterfalls, and rare species of animals and plants. Yunnan is also known for its vibrant and diverse cuisine. The province’s cuisine is influenced by the region’s ethnic minority groups, resulting in a unique blend of flavors and cooking styles. One of the most famous dishes in Yunnan is the ‘Crossing the Bridge Noodles,’ which is a rice noodle soup that is served with a variety of meats, vegetables, and seasonings. In conclusion, Yunnan province is a treasure trove of natural beauty, cultural heritage, and delicious cuisine. It has something to offer for everyone, from history buffs to nature lovers to foodies. Yunnan is undoubtedly one of the most fascinating and unforgettable destinations in China, and it is a place that everyone should visit at least once in their lifetime.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值