一、进制转换
1.1 进制
进制也就是进位计数制,是人为定义的带进位的计数方法。
也有一些不带进位的计数方法,比如原始的结绳计数法,唱票时常用的“正”字计数法,以及类似的tally mark计数。
对于任何一种进制---X进制,就表示每一位上的数运算时都是逢X进一位。
二进制 是逢二进一
八进制 是逢八进一
十进制 是逢十进一
十六进制 是逢十六进一
以此类推,x进制就是逢x进位。
1.2 数码、基数、位权
数码:数码是指数据中每一位的数字,例如在十进制中,数码为0-9。
基数:基数是指在某种进位计数制中,每个数位上能使用的数码的个数。例如,十进制的基数为 10,表示每个数位上可以使用0-9这10个数码。
位权:在多位数中,每个数位上的数码所代表的数值大小是由该位上的数码乘以基数的若干次幂得到的值。例如,在十进制中,从右到左,第一位(个位)的位权为10^0,第二位的位权为10^1,以此类推。
在计算机中,不同的数制(如二进制、八进制、十六进制)使用不同的基数和位权来表示数据。例如:
- 二进制:基数为2,数码为0和1,位权从右到左分别为2^0、2^1、2^2等。
- 八进制:基数为8,数码为0-7,位权从右到左分别为8^0、8^1、8^2等。
- 十六进制:基数为16,数码为0-9和A-F,位权从右到左分别为16^0、16^1、16^2等。
1.3 C语言中各进制的表示方法
1.3.1 二进制的表示方法
在C语言中,以数字0b开头的数字被视为二进制数。
int num = 0b1010; // 二进制数 1010 等于十进制数 10
1.3.2 八进制的表示方法
在C语言中,以数字0开头的数字被视为八进制数。
int num = 012; // 八进制数 12 等于二进制数 1010 等于十进制数 10
1.3.3 十进制的表示方法
在C语言中,十进制的数直接书写即可。
int num = 10;
1.3.4 十六进制的表示方法
在C语言中,以0x或0X开头的数字被视为十六进制数。
int num1 = 0xA; // 十六进制数 A 等于二进制数 1010 等于十进制数 10
int num2 = 0XB; // 十六进制数 B 等于二进制数 1010 等于十进制数 11
1.4 进制转换
1.4.1 二进制与十进制的转换
如上:
0b11101=1*2^4+1*2^3+1*2^2+0*2^1+1*2^0=16+8+4+0+1=29
如果为二进制的小数转换为十进制:
0b111.11=1*2^2+1*2^1+1*2^0+1*2^(-1)+1*2^(-2)=4+2+1+0.5+0.25=7.25
八进制、十六进制转换为十进制,皆可用二进制转换为十进制的算法。
1.4.2 十进制与二进制的转换
一个十进制数转换为二进制数要整数部分和小数部分分别转换,最后再组合到一起。
1.4.2.1 整数部分的转换
用 "除2取余,逆序排列"法。
具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
比如:125=0b1111101
1.4.2.2 小数部分的转换
用“乘 2 取整法”。
具体做法是:用十进制的小数乘以 2 并取走结果的整数(必是 0 或 1),然后再用剩下的小数重复刚才的步骤,直到剩余的小数为 0 时停止,最后将每次得到的整数部分按先后顺序从左到右排列即得到所对应二进制小数。
例如,0.8125=0b0.1101
十进制转换为八进制、十六进制,皆可十进制用转换为二进制的算法。
1.4.3 二进制与八进制的互换
采用421法:
1.4.4 二进制与十六进制的互换
二、原码、反码、补码
2.1 引入
整数的二进制表示方法有三种,即原码、反码、补码。
C语言中讨论的原码、反码、补码针对的是有符号整数。
有符号整数分为符号位和数值位两部分。
二进制序列中,最高位的一位被当做符号位,剩余的都是数值位。
符号位用 0 表示“正”,用 1 表示“负”。比如 1 和 -1 的二进制表示为:
00000001 // 1 的二进制表示 10000001 //-1 的二进制表示
正整数的原码、反码、补码都相同。
负整数的原码、反码、补码各不相同。
2.2 正整数的原码、反码、补码
000000001 // 1 的原码
000000001 // 1 的反码
000000001 // 1 的补码
011000000 // 96 的原码
011000000 // 96 的反码
011000000 // 96 的补码
正整数的原码、反码、补码都相同。
2.3 负整数的原码、反码、补码
负整数的原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
负整数的反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
负整数的补码:反码 +1 就可以得到补码。
反码得到原码也是可以使用:取反,+1 的操作。
10000001 // -1 的原码
11111110 // -1 的反码
11111111 // -1 的补码
11010100 // -84 的原码
10101011 // -84 的反码
10101100 // -84 的补码
负整数的原码、反码、补码各不相同。
2.4 补码的优点
对于整形来说:数据存放内存其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。