位运算小技巧总结(更新中 2020/4/24)

这篇博客汇总了位运算的各种实用技巧,包括交换数字、判断奇偶、位运算实现加减乘除、翻转二进制位、计数二进制1的数量,以及在输入输出和数值比较中的应用。随着时间的推移,作者不断更新了新的内容,如大小写字母转换、判断异号、优化除以十与乘以十的效率,还有快速的输入输出方法。

想到哪写到哪

交换两个数字

void swap(int & a, int & b){
    a ^= b;
    b ^= a;
    a ^= b;
}

判断奇偶

if(1 == (n & 1))    // 奇数
if(0 == (n & 1))    // 偶数

 

乘以二和除以二

n << 1 // 乘以二
n >> 1 // 除以二
n << x // 乘以二的x次方
n >> x // 除以二的x次方
n << 1 | 1 // 乘以二然后加一

 求最低位的1

#define lowbit(x) (x)&(-(x))

位运算实现加法

int add(int a, int b) {
	if (0 == b) {
		return a;
	}
	return add(a ^ b, (a & b) << 1);
}

位运算实现减法(从计算机组成原理里面学到的)

int sub(int a, int b) {
	return add(a, ~b + 1);
}

位运算实现乘法(快速幂的一个模板)

unsigned int mult(int a, int b) {
	unsigned int ans = 0;
	while (b) {
		if (1 == (b & 1)) {
			ans += a;
		}
		a = a << 1;
		b = b >> 1;
	}
	return ans;
}

交换数字的二进制中相邻的奇数位和偶数位

int exchange(int n) {
	return ((n & 0xaaaaaaaa) >> 1) + ((n & 0x55555555) << 1);
}

找到该数字的二进制中有多少个1

int calc(int n) {
	int count = 0;
	while (n) {
		n = n & (n - 1);
		count++;
	}
	return count;
}

2020/3/3 更新

大小写字母转换

char c;
/* 大写转小写 */
c | 0x20;
/* 小写转大写 */
c & 0xdf

位运算比较大小

int maximum(int a, int b) {
	int k = ((long long)a - (long long)b) >> 63;
	k = k & 1;
	return a * (k ^ 1) + b * k;
}

2020/3/5 更新

判断两个数是否异号

(x ^ y) < 0    // 小于0说明是异号的

2020/3/9 更新

做题目的时候用的read()函数(用来读入数据)

其中的0x30就是48,也就是'0',和-'0'的效果一样

inline int read() {
	int data = 0;
	char ch = getchar();
	while (ch < '0' || ch > '9') { ch = getchar(); }
	while ('0' <= ch && ch <= '9') { data = (data << 3) + (data << 1) + (ch ^ 0x30); ch = getchar(); }
	return data;
}

2020/4/7 更新

通过位运算加速除以十与乘以十

int x = 123456789;
int div10 = ((unsigned long long)x * 0x66666667L) >> 34;    //  除以十
int remain10 = x - ((div10 << 3) + (div10 << 1));    // 模十

2020/4/21更新

a=\biggl\lceil\frac{x+y}{2}\biggr\rceil\qquad

b=\biggl\lfloor\frac{x+y}{2}\biggr\rfloor

int a = (x | y) - ((x ^ y) >> 1);
int b = (x & y) + ((x ^ y) >> 1);

2020/4/24更新

位运算加速输出(快速IO,read函数在上面)

char out[1 << 10];
inline void write(int x) {
	if (x < 0) { 
		putchar('-'); 
		x = -x;
	}
	int cnt = 0;
	while (x > 0) {
		out[cnt++] = (x % 10) ^ '0';
		x = ((unsigned long long)x * 0x66666667L) >> 34;
	}
	while (cnt > 0) {
		putchar(out[--cnt]);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值