信号的表示和处理
- 进制的转换
任意进制的转换
- 信息的表现形式
磁盘,内存,中数据的表现形式以及存储方式
-
计算机是如何 + - * /
-
为什么使用补码进行计算
-
浮点数在计算机中是如何表示的,IEEE标准如何表示浮点数
-
代码是如何跑起来的 c/c++, java
一,任意进制转换
10进制转任意进制
- 10进制转2进制 将10进制数除以目标进制,直到商为0,余数倒置
同理 十进制转八进制就是将除以二换成除以八,十进制转十六进制将除数换成8
任意进制转10进制
方法:将每一位数乘以对应进制的权重值相加
任意进制转二进制
二进制转任意进制
八进制和16进制之间的转化
对于除了2进制,10进制,之外的其他进制之间的相互转化 比如8进制转16进制,16进制转8进制,都需要通过先转成2进制再进行转化
二,信息的表现形式
我们都知道硬盘上的存储的文件实际上就是存储着这些0和1的序列,那这些0101的序列又是如何表现的呢?
- 机械硬盘
机械硬盘的盘片上撒这一层磁粉,写入时,磁头线圈上加电,在周围产生磁场,磁化其下的磁性材料,也就是说用磁场的方向来表示0或者1
- 固态硬盘
固态硬盘主要是靠存储芯片来作为储存数据的介质,芯片里面分出了很多储存单元,这些储存单元里面有电子的位置;当一颗电子的位置里面没有存放电子,它就是0;如果存放了电子,它就是1。
- 内存
内存条是一个非常精密的部件,包含了上亿个电子元器件,它们很小,达到了纳米级别。这些元器件,实际上就是电路;电路的电压会变化,要么是 0V,要么是 5V,只有这两种电压。5V 是通电,用1来表示,0V 是断电,用0来表示。所以,一个元器件有2种状态,0 或者 1。
- 网络传输
网线是根据脉冲电信号,用不同的电压表示0或者1,网卡负责将电信号解析成二进制流。
- 无线网络
无线路由器通过天线发送无线电波到空中,无线网卡接收到无线路由器发出的无线电波和路由器形成回路,就能接收和发出信息了
三,计算机是如何 + - * /
- 首先了解一下 原码 反码 补码的概念
二进制 00000001 原码:00000001 反码:11111110 补码:00000001
二进制 10000001 原码:10000001 反码:01111110 补码: 11111111
正数的补码和其原码的一样的,负数的补码是其原码符号位不变其余位按位取反后+1
- 因为大部分的数字电路的CPU实现了加法器没有实现减法器,实现减法器是非常复杂的,所以CPU为了更方便的计算减法,将减法转换成加法来计算如:5-1 = 5+(-1)
举个减法的例子,5+(-1) 结果=4 二进制为 0000 0100
用原码计算
0000 0101 //5
1000 0001 //-1
1000 0110 //结果 != 0000 0100 错误
用反码计算
1111 1010 //5
1111 1110 //-1
1111 1000 //结果 != 0000 0100 错误
用补码计算
0000 0101 //5
1111 1111 //-1
0000 0100 //正数的补码还是本身 结果 == 0000 0100 正确
// 1 + (-2)
0000 0001 //1的补码
1111 1110 //-2的补码
1111 1111 // 再求补码 1000 0001 == -1 正确
正是因为CPU使用加法器来做减法,这种做法会导致二进制原码和反码计算结果出错,所以计算机使用补码进行计算和存储。
- 为什么一个字节表示的数是 -128到127 而不是 -127到127
因为计算机使用补码存储和计算,补码的0只有一个就是0000000,而原码中有+0和-0的区别,即 00000000 10000000 而补码中的10000000表示-128,所以多出了一位
- CPU + - * /都是通过加法和移位实现的
把除法转成乘法,乘法转成加法,减法也转成加法
乘法和除法由于涉及到寄存器的移位和逻辑门的一些知识前提,本次不深入探讨,会在之后介绍完CPU的工作原理之后再介绍
其实高级语言的编译器会对代码进行优化 2 x 14,c语言不会直接让CPU计算2 x14,而是转化成加法让CPU执行加法运算
例如 2 x 14 = 2 x (2^3 + 2^2 2^1 )
=(2 << 3) + (2 << 2) + (2 << 1)
=(00000010 << 3) + (00000010 << 2) + (00000010 << 1)
=00010000 + 00001000 + 00000100
=28
除法也是类似的只不过是向右移位
四,浮点数在计算机中是如何表示的,IEEE标准如何表示浮点数
- 浮点数的概念(IEEE754) 浮点数是计算机中用于表示实数的一种方法,类似于科学计数法,如:
314.4=3.144x102
0.00314=3.14x10-3
255=2.55x102
相当于数的小数点位置随比例因子的不同而在一定的范围内可以自由浮动。 由于电脑存储2进制长度有限,这种方法仅能近似的表示某个数。 c/c++,Java中存放浮点数遵守的标准是IEEE754
其定义如何用2进制来存储浮点数,根据公式:
V=(-1)N x M x 2R
N=为符号位,N=1,则为负数;N=0,则为整数
M=底数(尾数)
R=幂(指数)
- IEEE标准的几种格式
- 单精度(32位)
1(符号位)+8(指数)+23(底数)
2. 双精度(64位)
1(符号位)+11(指数)+52(底数)
3. 特殊值
无穷 : 指数全为1,底数全为0
NaN(not a number) : 指数全为1,底数不全为0
例如 单精度的263.3
二进制为 100000111.010011001...
而他的浮点数原码为 0100001110000011101001001100
想要了解IEEE具体的转化算法,可以去看 《深入理解计算机系统》 第二章
- 代码是如何跑起来的 c/c++, java
1.源程序文件 hello.c
hello.c在磁盘中是一0101的二进制序列存储的,为什么看到的是文本字符呢?
因为二进制的序列会经过编码集的转化,如下图:
2. 编译系统的组成
-
预处理阶段将源程序依赖的程序都导入进来
-
编译器阶段将源程序翻译为汇编指令代码(汇编是一种比C语言还低一级的语言)汇编的代码和Java语言的class文件代码很相似,但不相同
-
汇编器阶段将汇编代码打包成二进制序列(通过查表方式转为二进制,汇编指令和二进制有一一对应的指令表)
-
合并依赖程序并打包成可执行文件,可以被加载到内存中,由系统执行
Java代码是这么跑起来的
1.使用 javac 把 .java 源文件编译为字节码(文件后缀名为 .class)
2.字节码经过 JIT 环境变量进行判断,是否属于热点代码(多次调用的方法或循环体)
3.热点代码使用 JIT 编译为可执行的机器码
4.非热点代码使用解释器解释执行所有字节码
Java和C的区别是Java无需编译成汇编语言,直接编译成class字节码,放进JVM虚拟机的方法区,JVM根据代码的属性去判断是编译执行还是解释执行
问题:kotlin代码是如何跑起来的?JVM平台的其他语言是如何跑起来的?
总结:一种高级语言要变成目标机器的可执行二进制序列,一种是通过语言自带的编译器,编译为目标机器的二进制序列,二,还可以编译成一种中间结果,例如JVM的字节码,有虚拟机或者解释器负责转化为目标机器的二进制序列。