对位运算 负数位运算的理解

对位运算 负数位运算的理解

位运算大法好…
在这里,我拿洛谷P2104的题当作例题
题目:

小Z最近学会了二进制数,他觉得太小的二进制数太没意思,于是他想对一个巨大二进制数做以下 4 种基础运算:
运算 1:将整个二进制数加 1
运算 2:将整个二进制数减 1
运算 3:将整个二进制数乘 2
运算 4:将整个二进制数整除 2
小Z很想知道运算后的结果,他只好向你求助。
(Ps:为了简化问题,数据保证+,-操作不会导致最高位的进位与退位)
输入格式
第一行两个正整数 n,m,表示原二进制数的长度以及运算数。
接下来一行 n 个字符,分别为‘0’或‘1’表示这个二进制数。
第三行 m 个字符,分别为‘+’,‘-’,‘*’,‘/’,对应运算 1,2,3,4。
输出格式
一行若干个字符,表示经过运算后的二进制数。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10000005
int s[N];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		char t;
		cin>>t;
		s[i]=t-'0'; 
	}
	while(m--)
	{
		char ch;
		cin>>ch;
		if(ch=='+')s[n]++;
		else if(ch=='-')s[n]--;
		else if(ch=='*'){s[++n]=0;}
		else 
		{
			s[n-1]+=s[n]>>1;
			--n;
		}
	}
	for(int i=n;i>0;i--)
	{
		s[i-1]+=s[i]>>1;
		s[i]=s[i]&1;
	}
	for(int i=1;i<=n;i++)printf("%d",s[i]);
	return 0;
 } 

所实话,这道题玩了我一天,看答案看了许久,最后才知道怎么做。
首先,我们要先了解什么是位运算:

位运算基础
&
按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
|
按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1
^
按位异或
若参加运算的两个二进制位值相同则为0,否则为1
~
取反
~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1
<<
左移
用来将一个数的各二进制位全部左移N位,右补0
/>>
右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0

举个栗子:
&:
10001&10010=10000
|:
10010|11100=11110
/>>:(前面的 / 忽略不计,这里是因为不打 / 就打不出>> )
10010>>1=1001
<<:
1001<<1=10010
然而这些只是基本概念。下面聊聊我对>> << 的理解:
<< 是左移一位,因为计算机存储数据是二进值存储,所以将数据左移一位之后相当于整体扩大一倍,也就相当于ax2。
/>>是右移动一位,它的功能也就是除以2。以我们从小到大的经验,难点,易错点往往出再除法上。


对于负数位运算有一个基础点:无论是左移还是右移,这个数的符号位是不发生变化的,说简单点,就是负数怎么移还是负数,正数怎么移也就只能是0或者正数。


如果大家有兴趣的话可以在其他方看比较正统的负数右移的解释。但在这里我给一个比较简单的理解方式:
举个栗子:
3/2=1.5 而 3>>1=1
2/2=1 而 2>>1=1
-1/2=-0.5 而 -1>>1=-1
-2/2=-1 而 -2>>1=-1
-3/2=-1.5 而 -3>>1=-2
看到这里,相信聪明的你们已经发现规律了吧!
向右移以为就是除二取小有一点[1.5]=1 [-1.5]=-2的感觉。如果不知道 [ ] 是什么意思,那我也木的办法。


我讲这么多也就是解释下这一步是干什么的:

for(int i=n;i>0;i--)
	{
		s[i-1]+=s[i]>>1;
		s[i]=s[i]&1;
	}

至于这道题的题解,我觉得如果懂了负数的位运算,看我的代码应该都能懂了,如果不懂的可以取题解里看看大佬的发言(蒟蒻瑟瑟发抖

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值