操作符应用

发布于:2025-02-11 ⋅ 阅读:(102) ⋅ 点赞:(0)

一.二进制与进制转化

1.概念解析

我们常常能听见2进制,8进制,16进制这些讲法。他们都是数值的不同表达形式。根据不同的进制大小有着不同的权重比例。我们生活中常用的是10进制数,也就是逢10进1,由此推理至其他进制。例如2进制就是逢2进1。

2.进制转化

(1)10进制转化为2进制

如图将10进制的数不断对进制数进行取模,之后在将数除等原数,周而复始,最后将输出数导致就是原数转换的进制数。

fb0b3ea7a69d49e686e0e03a8871a79d.png

 

 (2)2进制转8进制

8进制中每一位都是0~7中的数字,0~7的数字各自写成2进制位最多有3个就足够了。所以我们将二进制位转换时,每次只需3位3位的进行转化。

(3)2进制转16进制

与上文同理,16进制位是由0~9,A~F直接的数组成的,用2进制表示最多只有4位。f6b559dd6add490f83a817e5afeb2fa9.png

 3.相关技巧与用法

例如给定x进制,x进制形式的数s,要将其转换为z进制形式。

思路为先将x进制的数s转化为10进制形式,再将该数转化为z进制形式。

将x进制的s转化为10进制形式有两种方法:

(1)逐位相乘法

int main()
{
	int x;
	int i = 0;
	string s;
	int ret = 0;
	cin >> x >> s;
	int n = s.size() - 1;
	while (n >= 0)
	{
		if (s[n] <= '9')
		{
			ret += (s[n--] - '0') * pow(x, i);
		}
		else
		{
			ret += (s[n--] - 'A' + 10) * pow(x, i);
		}
		i++;
	}
	cout << ret;
	return 0;
}

将每一位的数乘对应的权重转化为10进制相加。

(2)库函数调用

#include <string>
int main()
{
	int x;
	string s;
	cin >> x >> s;
	int ret = stoi(s, nullptr, x);
	cout << ret;
	return 0;
}

这里调用了stoi函数(string  to  int),将字符串转换为int形式,有三个参数,stoi(const string& str, size_t* idx = 0, int base = 10);。第一个参数为需要转化的字符串,第二个是一个指针,指向停止转化的字符;第三个参数是需要转换的进制(默认情况为10进制)。

在这里我们将字符串s转化为x进制。

(3)将10进制转化为z进制

string s = "0123456789ABCDEF";

void print(int ret, int m)
{
	if (ret > m)
	{
		print(ret / m, m);
	}
	cout << s[ret % m];
}

这里我们将10进制数设置为ret,需要转换的进制为m进制。我们使用一个递归,参照上面的(10进制转化为2进制的思路)。

二.位运算

1.概念解析

这里就做一些简单的介绍,重点内容在于后序的运用方法。

(1)左移右移操作符

最高的符号位不变,左移将二进制数整体左移动一位右边补0;右移将二进制整体右移一位,此时分为两种情况。如果是逻辑右移则左边用0进行填充,若是算术右移则左边用符号位进行填充。

(2)&(按位与)  |(按位或)  ^(按位异或)  ~(按位取反)

例a&b当a与b二进制位上都为1,得到的结果为1,否则为0。

例a|b当a与b二进制位上有1则为1,否则为0。

例a^b当a与b二进制位上相同则为0,不相同则为1。

例~a,将1变为0,将0变为1。

这里有个小tips:

所有的二进制操作都是先转化为补码的形式展开的,正数的原码反码补码都相同,负数将原码取反加1(符号位不变)得到的就是补码。

2.位运算的应用

(1)保留二进制位中的指定位

 有时候我们希望取出二进制中的某一位,使其他位变为0。我们只需要将对应的位进行(x&m)处理。

39a43ba5ff16416ebe506e6dd8e36aec.png

 (2)获取二进制中的指定位

当我们需要获取⼀个整数 x 的⼆进制中第 i 位(从低到⾼,以最低位为第 0 位是 1 还是 0 的时
候,我们可以对 x 做这样的运算: (x >> i) & 1 ,如果结果是 0 ,表⽰第 i 位是 0 ,如果结果是 1 ,表⽰第 i 位是 1 。
337c2b93d867446386b0ac561b1e9073.png

(3)将指定二进制位设置为1

设置 x ⼆进制中的某 1 位,也就是将 x ⼆进制中的第 i 位(从低到⾼,以最低位为第 0 位置为 1 ,则可以进⾏下⾯的运算: x |= (1<<i) ;
46342ab70d5a49a7b95c09ed8a71ad7b.png

 (4)将指定二进制位设置为0

将⼀个整数 x 的⼆进制表⽰中的某 1 位设置为 0 ,其余位置保留原值。也就是将 x 二进制中的第 i 位(从低到⾼,以最低位为第 0 位)置为 0 ,其他位保持不变,则可以进⾏下⾯的运算: x &= ~(1<<i)。
 

我们需要对指定位置设置为0,只需要对该位进行&1处理,而其他位需要&0处理。所以我们先将1移动到要置为0的位置,再按位取反,这样就只有该位得到0其余位都为1。

 c7f419e218fc4cda94b0fadf2e0ffb8f.png

(5)反转指定二进制位

使用一个数m,使得m的二进制位中的第i位为1其余设置为0,然后将(x^m)得到反转后的值。

由于按位取反中,若原数第i位为1,相同异或取反后变为0,若原数为0,与1异或取反后为1。30abb1676f0f444e9015de6812957a93.png

 (6)将二进制位最右边的1变为0

我们可以使用x  &(x-1)的方法x - 1让有1的最低的一位变为了0,而其他位不会改变。将其进行&,就可以消去最右边的那一位1。

8e09a3711acb4ccc9c45e2e08fbc3d8a.png

我们可以通过 x  &(x-1)的计算消除一位1,那么如果我们对一个数不断的进行消除1的操作,套上一个循环,就能计算出这个二进制数中1的个数。

一些其他用途:

这种思路有一个专有名词叫做位图(bitmap)。位图是数据结构操作系统常用的数据结构,他可以高效的快速释放资源 

(7)只保留二进制位中最右边的1

有时候,我们需要将⼀个整数 x 的⼆进制表⽰中最右边的 1 保留下来,其他位都置为 0 ,那么 x
&(-x) 就可以得到想要的数字。
af8674c7785c46068b950a68320d1de9.png

(8)异或的巧用

相同的两个数异或的结果为0;0与任何数x异或的结果为x;同时异或满足交换律a^b^a == a^a^b;

 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到