本次主要是总结进制之间的转换关系,以及计算机存储的二进制底层原理。通过我们不断深入了解计算机组成原理以及操作系统的知识,我们可以很轻松的学习一些编程知识。
上一章我们讲解了各类进制,有八进制、十进制、十六进制。
其实这里可以发现,所有进制都是可以被 ‘2’ 整除的。在计算机底层的原理就是以机器语言,也就是二进制,在和我们程序员在进行思想逻辑上的沟通交流。通过01代码把我们的10进制转换成二进制,从而让机器能“听懂”我们的语言。在这之前,我们先介绍一下二进制。
关于二进制:
二进制是计算机中用于表示和处理数字、文本和其他数据的一种编码系统。在C++中,可以使用二进制表示整数、字符和其他数据类型。
二进制是一种基于2的进制系统,只使用0和1两个数字来表示数值。与我们平常使用的十进制不同,十进制使用0到9这10个数字表示数值。
在C++中,可以使用二进制表示整数。例如,以0b或0B开头的数字表示二进制数。例如:
int binNum = 0b1010; // 表示十进制数10
C++还提供了一些用于处理二进制数的位操作运算符,例如与(&)、或(|)和异或(^)运算符。这些运算符可以用于执行位操作,如位与、位或和位异或。
此外,可以使用位移操作符(<<和>>)来进行二进制数的左移和右移操作。例如:
int num = 5; // 二进制表示为0b0101
int leftShiftedNum = num << 1; // 左移1位,得到0b1010,等于十进制数10
int rightShiftedNum = num >> 1; // 右移1位,得到0b0010,等于十进制数2
举例:将十进制数137转换为二进制数。
137 ÷ 2 = 68 余数 1
68 ÷ 2 = 34 余数 0
34 ÷ 2 = 17 余数 0
17 ÷ 2 = 8 余数 1
8 ÷ 2 = 4 余数 0
4 ÷ 2 = 2 余数 0
2 ÷ 2 = 1 余数 0
1 ÷ 2 = 0 余数 1
将余数从下往上排列,得到二进制数 10001001。
举例:将十进制数137转换为八进制数。
137 ÷ 8 = 17 余数 1
17 ÷ 8 = 2 余数 1
2 ÷ 8 = 0 余数 2
将余数从下往上排列,得到八进制数 211。
举例:将十进制数137转换为十六进制数。
137 ÷ 16 = 8 余数 9
8 ÷ 16 = 0 余数 8
将余数从下往上排列,得到十六进制数 89。
举例:将二进制数101011转换为十进制数。
1 * 2^5 + 0 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 32 + 0 + 8 + 0 + 2 + 1 = 43
所以,二进制数101011对应的十进制数是43。
举例:将八进制数52转换为十进制数。
5 * 8^1 + 2 * 8^0 = 40 + 2 = 42
举例:将十六进制数3A8转换为十进制数。
3 * 16^2 + 10 * 16^1 + 8 * 16^0 = 768 + 160 + 8 = 936
所以,十六进制数3A8对应的十进制数是936。
增加:
关于2的次幂的一些东西:我们在开发的过程中经常会遇见使用2的多少次幂的情况,比较常见的就是1024、512、256、2048、4096、这样的数值,其实这就是对应的2的次幂我们需要牢记。
2的0次幂到2的15次幂的结果如下:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
1.13.3 其他进制转换
8转2:每一位八进制数转换为对应的三位二进制数。
举例:将八进制数36转换为二进制数。
3 => 011
6 => 110
八进制36对应二进制011110
2转8:可以将二进制数从右往左每三位一组,并将每组二进制数转换为对应的八进制数。
举例:将二进制数110101转换为八进制数。
1 101 01
然后,将每组三位二进制数转换为对应的八进制数:
1 => 1
101 => 5
01 => 1
二进制数110101对应的八进制数是151。
2转16:可以将二进制数从右往左每四位一组,并将每组四位二进制数转换为对应的十六进制数。
举例:将二进制数10111011转换为十六进制数。
1 0111 0111
每组四位二进制数转换为对应的十六进制数
1 => 1
0111 => 7
0111 => 7
二进制数10111011对应的十六进制数是177。
我们通常先将要转换的进制先转成二进制,然后再通过二进制计算得出相应的进制。二进制是基础,如果你使用电脑自带的计算机,可以使用程序员模式进行计算,可以尝试一下是不是这样的。我说的一些基本原理,大概是需要你动脑思考它的转换过程,和方法。如果需要笔算的时候,你也能知道其原理是什么。
将八进制转换为十六进制时,可以先将八进制数转换为二进制数,再将二进制数转换为十六进制数。
举例:将八进制数73转换为十六进制数。
首先,将八进制数73转换为二进制数:
7 => 111
3 => 011
将转换后的二进制数分组,每四位一组:
111 011
//这里其实就是0111 0011每四位为一位。不够位数的都是前面补0
然后,将每组二进制数转换为对应的十六进制数:
0111 => 7
0011 => 3
所以,八进制数73对应的十六进制数是73。
将十六进制转换为八进制时,同上理:
举例:将十六进制数AC转换为八进制数。
首先,将十六进制数AC转换为二进制数:
A => 1010
C => 1100
将转换后的二进制数分组,每三位一组:
101 011 00
然后,将每组二进制数转换为对应的八进制数:
101 => 5
011 => 3
00 => 0
所以,十六进制数AC对应的八进制数是530。
原码(Sign-Magnitude)是一种表示有符号整数的方法,其中最高位为符号位(0表示正数,1表示负数),其余位表示数值的绝对值。(无符号整数的三码相同)
例如,假设我们使用8位二进制数表示整数,那么以下是一些示例:
正数 +3 的原码: 0000 0011
负数 -3 的原码: 1000 0011(这里-3的原码的第一位“1”对应的就是负数的 - ,
而二进制11表示2^1 + 2^0 = 2+1 =3,最后其表示的就是-3
原码的第一位表示“符号位”,0为正,1为负。)
反码(One's Complement)是在原码的基础上,负数的表示方法发生了变化。正数的反码与原码相同,而负数的反码是将原码中除符号位外的每一位取反(0变为1,1变为0)。
例如,使用8位二进制数表示整数,以下是一些示例:
正数 +3 的原码: 0000 0011,反码: 0000 0011
负数 -3 的原码: 1000 0011,反码: 1111 1100
补码(Two's Complement)是在反码的基础上进一步转换得到的,负数的表示方法发生了变化。负数的补码是将反码中的每一位取反,然后再加1。
例如,使用8位二进制数表示整数,以下是一些示例:
正数 +3 的原码: 0000 0011,反码: 0000 0011,补码: 0000 0011
负数 -3 的原码: 1000 0011, 反码: 1111 1100, 补码: 1111 1101
计算机存储的就是补码形式:
补码的优势在于可以对正数和负数进行相同的加法和减法运算,同时使用补码可以避免出现正零和负零的问题。在计算机中,大多数情况下使用补码来表示有符号整数。
(这里后期开操作系统和组成原理的专栏进行详细讲总结)
+0补码:0000 0000
-0补码:QQQ 0000
假如:没有补码8-6
8:0000 1000
-6:1000 0110
-------
1001 0000---->-16结果负16不对
有补码8-6的情况下
10:0000 1000
-6 :1111 1010(此时是负整数,需要把原码--->反码+1--->补码
原码---10000110
反码---11111001
补码---11111010)
(补码原则:反码的符号位不变,其他按位取反,最后+1)
------最终结果就是
0000 0100---->4 就是我们正常十进制计算的结果
补码相加的计算方法如下:
1. 将两个补码按位相加,忽略最高位的进位。
2. 如果相加的结果有进位,则说明结果溢出了。
3. 如果结果没有溢出,则最终的和即为补码相加的结果。
接下来,以具体的例子说明补码相加的计算过程。
假设我们要计算两个有符号整数的补码相加:A + B。
1. 将 A 和 B 的补码按位相加,忽略最高位的进位。
- 如果 A 和 B 相同位置的位都是 0 或都是 1,则相加结果位为 0。
- 如果 A 和 B 相同位置的位一个是 0,另一个是 1,则相加结果位为 1。
2. 判断是否有进位。
- 如果有进位,则表示结果溢出,需要进行溢出处理。
- 如果没有进位,则结果没有溢出。
3. 最后的结果即为补码相加的结果。
需要注意的是,在计算机中进行补码相加时,仍然使用有限位数来表示结果,所以当结果溢出时,会丢弃最高位的进位。
负数在计算机以补码的方式存储
非负数在计算机以原码的方式存储
八进制数 以原码存储
十六进制 以原码存储
以十六进制查看内存数据存储情况
如果是对 无符号变量 进行取值,输出内存的原本存储的原始的数据
如果是对 有符号变量 进行取值,系统会先检查内存中存取数值的的最高位,
如果最高位为0表正数,内存原始进行输出。
如果最高位为1表负数,将内存数据补码运算(得到原码) 输出