文章目录
- 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的各种进制表示形式:
12的2进制:1010
12的8进制:14
12的10进制:12
12的16进制: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…
如下图:
2进制和10进制是类似的,只不过2进制的权重,从右往左一次是20,21,22。
如果2进制是1101,该怎么理解呢?
如下图:
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进制。
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
3. 8、10、16进制转2进制
3.1 10进制转2进制
- 方法1:用10进制数除2,记录每次所得余数,如果所得的商不为0就继续除,直到所得商为0为止,所得余数从下往上就是10进制转换出的2进制。如下图:
- 方法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。
3.3 16进制转2进制
16进制转2进制,只需要将16进制转换为4位对应的2进制即可
例如:6b转换为2进制为:0110 1011。
4.原码、反码、补码
- 整数的2进制有三种表示方法:原码、反码、补码
- 有符号整数的三种表示方法中均有符号位和数值位,2进制序列中,最⾼位的1位是被当做符号位,剩余的都是数值位。
- 符号位都是⽤0表⽰“正”,⽤1表⽰“负”。
- 正整数的原、反、补码都相同,如下
- 负整数的三种表示方法各不相同,变化规则如下:
- 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
- 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
- 补码:反码+1就得到补码。
3. 补码转换为原码
- 方法1:补码-1,再取反
- 方法2:符号位不变,其他位按位取反,再+1
对于整型来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算 过程是相同的,不需要额外的硬件电路
5.移位操作符(<< >>)
在内存中,整数都是按补码来存储的,所以我们在对2进制位进行操作时,操作的都是补码,而我们看到的全都是原码
注:移位操作符的操作数只能是整数。
5.1左移操作符
移位规则:左边丢弃、右边补0
5.2 右移操作符
右移操作符根据不同的编译器,分为 逻辑右移 和 算术右移(大部分编译器为算术右移)
- 逻辑右移:左边⽤0填充,右边丢弃
- 算术右移:左边⽤原该值的符号位填充,右边丢弃
注意:对于移位运算符,不要移动负数位,这个是标准未定义的。
6.位操作符(& | ^ ~)
它们的操作数也必须是整数
6.1 &
按位与原则:对应的二进制位进行运算,都为1才是1,否则为0
6.2 |
按位或原则:对应二进制进行运算,只要有1就为1,都为0才是0
6.3 ^
按位异或的原则:相同为0,相异为1。
6.4 ~
按位取反原则:所有位直接取反
7.相关题目
- 不能创建临时变量(第三个变量),实现两个数的交换
首先要明白一点: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;
}
- 求⼀个整数存储在内存中的⼆进制中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;
}
- 编写代码将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;
}