进制转换:
日常生活中使用的是十进制数据,由于计算机的物理特性导致它只能识别二进制数据,我们在编程时使用的10进制数据,会被计算机转换成二进制数据再运算,为了理解编程时的一些奇怪现象,我们需要掌握二进制数据、八进制数据、十六进制数据。
二进制数据:
由0~1两个数字组成,逢2进1,由于计算机的运算器只能识别高低两种电流,所以它在运算时只能识别二进制数据。
十进制转换成二进制:
假如把x转换成二进制,x/2记录下余数,然后对商继续除以2,重复这个过程,直到商为0结束,然后把记录的余数倒序汇总,就得到了x的二进制。
例如:117转换成二进制 117 / 2 余数1 58 / 2 余数0 29 / 2 余数1 14 / 2 余数0 7 / 2 余数1 3 / 2 余数1 1 / 2 余数1 0 117的二进制就是:1110101
八进制数据:
由0~7八个数字组成,逢8进1,早期使用它记录二进制数据,现在基本不再使用,文件的权限还依然使用8进制数据表示,所以还无法退出历史。
二进制数据转换八进制:
三位二进制对应一位八进制。
000 0 001 1 010 2 011 3 100 4 101 5 110 6 111 7
注意:
在C代码中,以0开头的是八进制数据,以%o输出的也八进制数据。
十六进制数据:
由0~9和a~f十六个字符组成,随着计算机的发展CPU的位数越来越多,输出的二进制也越来越长,随后科学家又发明出十六进制用于记用二进制数据。
二进制转换成十六进制:
四位二进制对应一位十六进制,超过9的用字母ABCDEF表示(不区分大小写)。
1000 8 1001 9 1010 a 1011 b 1100 c 1101 d 1110 e 1111 f
注意:
在C代码中,以0x开头的是十六进制数据,以%x,%p输出的是十六进制数据。
0713
任意进制转换成十进制:
每一个非0位带该公式求和 v*b^(n-1) 就得到了十进制。 v 值 b 进制 n 位数
关于进制转换可能遇到的笔试题:
1、十进制转换成二进制、八进制、十六进制(以%o或%x为输出占位符)
统一先转换成二进制,然后再把二进制转换成八进制或十六进制。
2、在代码阅读题中遇到0123或0xabcdf
0开头的是8进制,0x开头的是十六进制,可以先转换成二进制再转换10进制,然后再运算。
3、输入一个整数转换成N进制(2<= N <= 35)
原码、反码、补码:
原码:
整数的绝对值转换成二进制,叫原码。
反码:
原码按位求反,叫反码。
补码:
正数的原码就是补码,负数的反码+1是补码。
十进制的数据是以补码形式存储在计算机中的,因为计算机的CPU中只有加法器,也就是只能运算加法,其它运算都是使用加法模拟的。
为了能计算出a-b也就是a + -b 所以需要使用特殊格式存储负数。
// 以8位计算机为例 24 - 15 24 + -15 00001111 -15的原码 11110000 -15的反码 11110001 -15的补码 00011000 24的补码 00001001 结果是9 // 以32位计算机为例 00000000 00000000 00000000 00001111 -15的原码 11111111 11111111 11111111 11110000 -15的反码 11111111 11111111 11111111 11110001 -15的补码 00000000 00000000 00000000 00011000 24的补码 00000000 00000000 00000000 00001001 结果是9 0xfffffff1
补码转换成十进制整数:
补码的两种解析方式:
无符号解析:
由于无符号数据全部是正数,所以补码就是原码,直接转换成十进制即可。
有符号解析:
根据补码的最高位判断它是整数的补码还是负数的补码。
最高位是1:它必然是负数的补码。
1、补码-1得到反码
2、反码按位求反,得到原码
3、原码转换成十进制数据,并在结果的前面加上负号。
最高位是0:它必然是正数的补码,直接转换成十进制即可。
int num = 11111111 11111111 11111011 00101110; 1、由于最高位是1,它必须是负数的补码 2、补码-1 得到反码 11111111 11111111 11111011 00101101 3、反码 按位求反 得到 原码 00000000 00000000 00000100 11010010 1024+128+64+16+2 -1234
注意:
当遇到补码转换成十进制数据的笔试题时,必须有是否是有符号信息。
// 假如以下变量的补码是10110011,代码会输出什么,补码的符号信息已经包含在代码中了 char num; printf("%hhd",num); 10110011 10110010 01001101 64+8+4+1 -77 // 把以下补码转换成十进制数据,条件不够充分 11001100
注意:
一个整型变量的取值范围是环型状的,当它是最大值时再加1就会变成最小值,当它是最小值时减1就是变成最大值。
以char类型数据为例: -128 10000000 补码 01111111 -1后的补码,转换成十进制的结果是127 127 01111111 补码 10000000 加1后的补码,转换成十进制的结果是-128 char特殊的补码: 10000000 最小值(最高位是1,其余全是0) 01111111 最大值(最高位是0,其余全是1) 11111111 -1(所有二进制位都是)// 以下循环执行多少次: char cnt = 7, n = 0; while(cnt) { cnt -= 3; n++; } printf("%hhd\n",n); 7 45 -128 1 125 42 -1 42 -127 1 126 42 0 173
位运算符:
位运算符是针对数据的补码进行运算。
A & B 按位与运算,它是针对数据的补码进行按位与运算 0 & 0 结果是0 0 & 1 结果是0 1 & 0 结果是0 1 & 1 结果是1 A | B 按位与运算 0 | 0 结果是0 0 | 1 结果是1 1 | 0 结果是1 1 | 1 结果是1 A ^ B 按位异或运算 0 ^ 0 结果是0 0 ^ 1 结果是1 1 ^ 0 结果是1 1 ^ 1 结果是0 ~A 按位求反,是单目运算符 ~0 结果是1 ~1 结果是0 x << n 把x的补码前n位丢掉,末尾补上n个0,按位左移。 10101100 << 3 01100000 x >> n 把x的补码后n位丢掉,前面n位,如果x是正数则补0,如果是负数则补1。 char num = -3; printf("%hhd\n",num >> 2+1);