算法学习笔记(5)-------位运算的tips

在计算机中所有数据都是以二进制的形式储存的。位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快。

在实际编程中,如果能巧妙运用位操作,完全可以达到四两拨千斤的效果,正因为位操作的这些优点,所以位操作在各大IT公司的笔试面试中一直是个热点问题。

以下就位运算的小诀窍进行总结供自己学习,大部分来自网上的。

  1. 交换两个整数(注意:在编译器中,针对double或float的位运算会报错)

int swap(int &a, int &b)
{
	if (a != b)
	{
		a ^= b;
		b ^= a;
		a ^= b;
	}
	return 0;
}

我们可以这样理解,第一步a=a^b,第二步b=a^b=(a^b)^b=a^(b^b)=a;第三步:a=a^b=(a^b)^a=(a^a)^b=b,交换完毕,不太理解的话可以自己写一个数的二进制进行测试。

  1. 变换符号--------变换符号就是将一个数从正数变到负数,从负数变到整数

    例如:8-----00001000,对该数取反,为11110111+1----11111000------ -8

  2. int SignReversal(int a)
    {
    	return (~a + 1);
    }

    求绝对值------

首先判断这个数是否是负数,将其右移31位,得到符号位,符号位为-1则是负数,符号位是0则是正数。由交换符号推导可知,负数专为整数则位取反+1

int abs(int a)
{
	int flag = (a >> 31);
	return (flag == 0) ? a: (~a + 1);
}

对以上的方法代码还可以进行优化,我们知道,任何一个数与0亦或等于本身,与-1即0XFFFFFFFF亦或相当于位取反,再加一就是对该数交换符号。故代码可以如下所写:

int myAbs(int a)
{
	int flag = (a >> 31);
	return ((a^flag) - flag);
}

高低位交换----------

给出一个无符号的16位数,称这个数的前8位为"高位",后8位为"低位", 要求将这个数的"高位"转为"低位",“低位”转为“高位”。假设这个数的16位为x1x2x3x4x5x6x7x8 y1y2y3y4y5y6y7y8,将其位右移8位,则高位自动补0,结果为00000000 x1x2x3x4x5x6x7x8,再将该数位左移8位,其低位自动补0,y1y2y3y4y5y6y7y8 00000000,将这两个结果亦或即可将高低位交换,代码如下:

#include<iostream>
#include<string>
using namespace std;
template <class T> 
void printBinary(T a)
{
	for (int i=sizeof(a)*8-1; i>=0; i--)
	{
		if ((a >> i) == 1)
			cout <<'1';
		else 
			cout << '0';
		if (i == (sizeof(a)*8-1)/2+1)
			cout <<' ';
	}
	cout << endl;
}

int main()
{
	unsigned short a;
	unsigned short b;
	cin >> a;
	b = ((a>>8)|(a<<8));
	printBinary(a);
	printBinary(b);
	return 0;
}


你可能感兴趣的:(算法学习笔记(5)-------位运算的tips)