利用位操作实现逆序

二进制逆序

我们知道如何对字符串求逆序,现在要求计算二进制的逆序,如数34520用二进制表示为:

      10000110 11011000

将它逆序,我们得到了一个新的二进制数:

      00011011 01100001

它即是十进制的7009。

    回顾下字符串的逆序,可以从字符串的首尾开始,依次交换两端的数据。在二进制逆序我们也可以用这种方法,但运用位操作的高低位交换来处理二进制逆序将会得到更简洁的方法。类似于归并排序的分组处理,可以通过下面4步得到16位数据的二进制逆序:

第一步:每2位为一组,组内高低位交换

      10 00 01 10  11 01 10 00

  -->01 00 10 01 11 10 01 00

第二步:每4位为一组,组内高低位交换

      0100 1001 1110 0100

  -->0001 0110 1011 0001

第三步:每8位为一组,组内高低位交换

      00010110 10110001

  -->01100001 00011011

第四步:每16位为一组,组内高低位交换

      01100001 00011011

  -->00011011 01100001

对第一步,可以依次取出每2位作一组,再组内高低位交换,这样有点麻烦,下面介绍一种非常有技巧的方法。先分别取10000110 11011000的奇数位和偶数位,空位以下划线表示。

      原 数    100001111011000

      奇数位 1_0_0_1_ 1_0_1_0_

      偶数位  _0_0_1_0 _1_1_0_0

将下划线用0填充,可得

      原 数    100001111011000

      奇数位 100000110001000

      偶数位 00000100 01010000

再将奇数位右移一位,偶数位左移一位,此时将这两个数据相或即可以达到奇偶位上数据交换的效果了。

      原 数           100001111011000

      奇数位右移 01000001 01000100  

      偶数位左移 000010010100000

      相或得到      01001001 11100100

可以看出,结果完全达到了奇偶位的数据交换,再来考虑代码的实现——

      取x的奇数位并将偶数位用0填充用代码实现就是x & 0xAAAA

      取x的偶数位并将奇数位用0填充用代码实现就是x & 0x5555

因此,第一步就用代码实现就是:

       x = ((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1);

类似可以得到后三步的代码。完整程序如下:

//二进制逆序 by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  
#include <stdio.h>
template <class T>
void PrintfBinary(T a)
{
	int i;
	for (i = sizeof(a) * 8 - 1; i >= 0; --i)
	{
		if ((a >> i) & 1)
			putchar('1');
		else 
			putchar('0');
		if (i == 8)
			putchar(' ');
	}
	putchar('\n');
}
int main()
{
	printf("二进制逆序 --- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  ---\n\n");

	printf("逆序前:    ");
	unsigned short a = 34520;
	PrintfBinary(a);

	printf("逆序后:    ");	
	a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1);
	a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2);
	a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4);
	a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8);
	PrintfBinary(a);
}

本文为转载,原文是:http://blog.youkuaiyun.com/morewindows/article/details/7354571

转载于:https://my.oschina.net/nibnat/blog/197134

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值