【二进制转换和与其有关的操作符详解】

文章目录

  • 1.二进制与进制转换
  • 2. 2进制转8、10、16进制
    • 2.1 2进制转10进制
    • 2.2 2进制转8进制
    • 2.3 2进制转16进制
  • 3. 8、10、16进制转2进制
    • 3.1 10进制转2进制
    • 3.2 8进制转2进制
    • 3.3 16进制转2进制
  • 4.原码、反码、补码
  • 5.移位操作符(<< >>)
    • 5.1左移操作符
    • 5.2 右移操作符
  • 6.位操作符(& | ^ ~)
    • 6.1 &
    • 6.2 |
    • 6.3 ^
    • 6.4 ~
  • 7.相关题目

在这里插入图片描述

1.二进制与进制转换

我们经常能听到2进制、8进制、10进制与16进制这样的讲法,那是什么意思呢?其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。
比如:数值12的各种进制表示形式:

122进制:1010
128进制:14
1210进制:12
1216进制:C

我们重点介绍⼀下⼆进制:
⾸先我们还是得从10进制讲起,其实10进制是我们⽣活中经常使⽤的,我们已经形成了很多尝试:

  • 10进制中满10进1
  • 10进制的数字每⼀位都是0~9的数字组成

其实⼆进制也是⼀样的

  • 2进制中满2进1
  • 2进制的数字每⼀位都是0~1的数字组成

2. 2进制转8、10、16进制

2.1 2进制转10进制

其实10进制的123表示的值是⼀百⼆⼗三,为什么是这个值呢?其实10进制的每⼀位是有权重的,10进制的数字从右向左是个位、⼗位、百位…,分别每⼀位的权重是 100 , 101 , 102
如下图:
【二进制转换和与其有关的操作符详解】_第1张图片
2进制和10进制是类似的,只不过2进制的权重,从右往左一次是20,21,22
如果2进制是1101,该怎么理解呢?
如下图:
【二进制转换和与其有关的操作符详解】_第2张图片

2.2 2进制转8进制

8进制的数字每⼀位是0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了。
如下:

0的二进制:000
1的二进制:001
2的二进制:010
3的二进制:011
4的二进制;100
5的二进制:101
6的二进制:110
7的二进制:111

所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀个8进制位,剩余不够3个2进制位的直接换算
如:2进制的01101011,换成8进制:0153,0开头的数字,会被当做8进制。
【二进制转换和与其有关的操作符详解】_第3张图片

2.3 2进制转16进制

和2进制转8进制类似
16进制的数字每一位是0-9,A-F的数字,如果每一位写成2进制的形式,最多4个二进制位就足够了。
如下:

0的二进制:0000			8的二进制:1000	
1的二进制:0001			9的二进制:1001
2的二进制:0010			A的二进制:1010
3的二进制:0011			B的二进制:1011
4的二进制;0100			C的二进制:1100
5的二进制:0101			D的二进制:1101
6的二进制:0110			E的二进制:1110
7的二进制:0111			F的二进制:1111

所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算
如:2进制的01101011,换成16进制:0x6b,16进制表⽰的时候前⾯加0x
【二进制转换和与其有关的操作符详解】_第4张图片

3. 8、10、16进制转2进制

3.1 10进制转2进制

  • 方法1:用10进制数除2,记录每次所得余数,如果所得的商不为0就继续除,直到所得商为0为止,所得余数从下往上就是10进制转换出的2进制。如下图:

【二进制转换和与其有关的操作符详解】_第5张图片

  • 方法2:拼凑法。这种方法需要熟记2进制所表示的10进制数。

20=1,21=2,22=4,23=8,24=16,25=32,26= 64,27=128,28=256,29=512,210=1024
例如:125= 64+32+16+8+4+1
所以,123的二进制就可以这样写:1111101
在这里插入图片描述

3.2 8进制转2进制

8进制转2进制,只需要将8进制转换为3位对应的2进制即可
例如:153转换为2进制为01 101 011。
【二进制转换和与其有关的操作符详解】_第6张图片

3.3 16进制转2进制

16进制转2进制,只需要将16进制转换为4位对应的2进制即可
例如:6b转换为2进制为:0110 1011。
【二进制转换和与其有关的操作符详解】_第7张图片

4.原码、反码、补码

  • 整数的2进制有三种表示方法:原码、反码、补码
  • 有符号整数的三种表示方法中均有符号位数值位,2进制序列中,最⾼位的1位是被当做符号位,剩余的都是数值位。
  • 符号位都是⽤0表⽰“正”,⽤1表⽰“负”。
  1. 正整数的原、反、补码都相同,如下

【二进制转换和与其有关的操作符详解】_第8张图片

  1. 负整数的三种表示方法各不相同,变化规则如下:
  • 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
  • 反码:将原码的符号位不变其他位依次按位取反就可以得到反码。
  • 补码:反码+1就得到补码。

【二进制转换和与其有关的操作符详解】_第9张图片
3. 补码转换为原码

  • 方法1:补码-1,再取反

【二进制转换和与其有关的操作符详解】_第10张图片

  • 方法2:符号位不变,其他位按位取反,再+1

【二进制转换和与其有关的操作符详解】_第11张图片

对于整型来说:数据存放内存中其实存放的是补码。

为什么呢?
在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算 过程是相同的,不需要额外的硬件电路

5.移位操作符(<< >>)

在内存中,整数都是按补码来存储的,所以我们在对2进制位进行操作时,操作的都是补码,而我们看到的全都是原码
注:移位操作符的操作数只能是整数

5.1左移操作符

移位规则:左边丢弃、右边补0
【二进制转换和与其有关的操作符详解】_第12张图片
【二进制转换和与其有关的操作符详解】_第13张图片

5.2 右移操作符

右移操作符根据不同的编译器,分为 逻辑右移算术右移(大部分编译器为算术右移)

  1. 逻辑右移:左边⽤0填充,右边丢弃
  2. 算术右移:左边⽤原该值的符号位填充,右边丢弃

【二进制转换和与其有关的操作符详解】_第14张图片

【二进制转换和与其有关的操作符详解】_第15张图片
【二进制转换和与其有关的操作符详解】_第16张图片

注意:对于移位运算符,不要移动负数位,这个是标准未定义的。

6.位操作符(& | ^ ~)

它们的操作数也必须是整数

6.1 &

按位与原则:对应的二进制位进行运算,都为1才是1,否则为0
【二进制转换和与其有关的操作符详解】_第17张图片

6.2 |

按位或原则:对应二进制进行运算,只要有1就为1,都为0才是0
【二进制转换和与其有关的操作符详解】_第18张图片

6.3 ^

按位异或的原则:相同为0,相异为1。
【二进制转换和与其有关的操作符详解】_第19张图片

6.4 ~

按位取反原则:所有位直接取反
【二进制转换和与其有关的操作符详解】_第20张图片

7.相关题目

  1. 不能创建临时变量(第三个变量),实现两个数的交换

首先要明白一点:0^0=0 a^0=a; a^a=0 即:一个数和0异或是它本身,两个相同的数异或是0

int main()
{
	int a = 3;
	int b = 5;
	printf("a=%d b=%d\n", a, b);
	a = a ^ b;
	b = a ^ b;  //(a^b^b)
	a = a ^ b;	//(a^a^b)
	printf("a=%d b=%d\n", a, b);
	return 0;
}

【二进制转换和与其有关的操作符详解】_第21张图片

  1. 求⼀个整数存储在内存中的⼆进制中1的个数

方法1:与1按位与不等于

a & 1 = 1;a的二进制位的最低位是1
a & 1 = 0; a的二进制位的最低位不是1

int main()
{
	//00000000000000000000000000000001   1
	
	//10000000000000000000000000000001   -1
	//11111111111111111111111111111110  -1反码
	 
	//11111111111111111111111111111111   -1补码
	//00000000000000000000000000000001
	//00000000000000000000000000000001
	//n 的二进制位的最低位&1,如果结果是1,那么就说明最低位是1
	//所以,我们要想办法让1动起来
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
		if ((n & (1 << i)) != 0 )
		{
			count++;
		}
	}
	printf("%d\n", count);
	return 0;
}

方法2:基于公式 n = n & (n-1)

int main()
{
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	printf("%d\n", count);
	return 0;
}
  1. 编写代码将13⼆进制序列的第5位修改为1,然后再改回0
int main()
{
	int n = 13;
	n = n | (1 << 4);
	printf("%d\n", n);
	//000000000000000000000000000001011
	//000000000000000000000000000010000   1<<4
	//000000000000000000000000000011011
	
	n = n & (~(1 << 4));
	printf("%d\n", n);
	//000000000000000000000000000011011
	//111111111111111111111111111101111    ~(1<<4)
	//000000000000000000000000000001011
	return 0;
}

你可能感兴趣的:(C_language,c语言,开发语言)