算法_位运算x&(-x)和x&(x-1)

最近在跟着y总学算法。

今天学到了两个很经典的位运算,x&(-x)和x&(x-1):

x&(-x):保留二进制下最后出现的1的位置,其余位置置0(即一个数中最大的2的n次幂的因数

x&(x-1):消除二进制下最后出现1的位置,其余保持不变

第二个算法我之前写过博客,C语言求a的二进制表示中有几个1_工业废气的博客-优快云博客

那么问题就在于第一个算法,有什么作用?

目录

-x的含义

当x为奇数时

当x为偶数时

当x为0时

将偶数拆成一个偶数和奇数相乘

LowBit


-x的含义

-x在计算机存储是用x的补码存储,是在x的值的基础上按位取反(~x)后再加1,也就是说:

x & -x == x & (~x + 1)

当一个奇数加1时,它表示的二进制数则会发生进位,这样最低位的那些连续的1都会成为0,比如:

0000000001111111 + 1 = 0000000010000000

当x为奇数时

举个例子:

000001001111按位取反后就成为了111110110000。那么再加上1就成为了111110110001。

将两个数进行按位与操作:

000001001111 & 111110110001 = 000000000001

也就是说,当一个奇数与它的负值按位与时,结果为1

当x为偶数时

再举个例子:

000001001110按位取反后就成为了111110110001。再加上1就成为了111110110010。

将两个数进行按位与操作:

000001001110 & 111110110010 = 000000000010

这个值与原值的末位0的个数是一致的,而且这个结果只有一位值是1, 其他位均是0。

二进制000001001110的十进制是78,而二进制10的十进制是2,是能整除78的最大的2的幂。

当一个偶数与它的负值相与时,结果是能整除这个偶数的最大的2的幂。

即:当x为偶数时,m = x & -x , 则 x % m = 0, 且 m = 2^k

当x为0时

当x为0时,x&(-x)的结果为0。

将偶数拆成一个偶数和奇数相乘

请看代码:

#include <stdio.h>
int main()
{
	int x = 0;
	printf("请输入要拆分的偶数\n");
	scanf("%d",&x);
	if ((x & (-x)) == 1)
	{
		printf("%d是奇数", x);
	}
	else if ((x & (-x)) == 0)
	{
		printf("%d是零", x);
	}
	else 
	{
		int even_number = x & (-x);
		int odd_number = x / even_number;
		printf("%d = %d × %d", x, even_number, odd_number);
	}
	return 0;
}

当输入48时,输出结果如下:

LowBit

x&(-x)一般是用来获取某个二进制数的LowBit,在树状数组中会用到。
LowBit(x)是x的二进制表达式中最低位的1所对应的值。

int LowBit(int x)
{
    return x & (-x);
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值