1.反码和补码和移码
(1)正数的原码,补码,反码是一样的,并且符号位第一位是0,例如:9的原码:00001001 反码:00001001 补码:00001001
(2)负数的第一位为1(符号位),反码:符号位不变,数值位按位取反,补码:反码+1
减法转换为加法的思想是补数,时钟的思想
(3)计算机中数字以补码储存,因为原码和反码计算不准确,而补码是准确的。
例如:9+(-8)=1
如果用原码:00001001+10001000=10010001即-17 错误。
如果用补码:00001001+11111000=00000001 原码为00000001 即1
(4)第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:(原码表示)
[1111 1111 , 0111 1111],第一位为符号位,后面七位为真值,00000000和10000000都表示0
(5)使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]. 补码不存在-0,保留了+0,-0刚好是用来表示-128 tips:-1 + -127用补码运算刚好等于-128, 即10000000
(6)8位是2的8次方,256个数,-127到+127一共255个数,那么还差一位,也是就是重复的+0和-0,那么在补码运算中-127+ -1 刚好等于-128即10000000,所以范围为-128到+127,所以32位整数的取值范围就是-2的31次方到+2的31次方 - 1
(7)uint32无符号32位整数,范围是0 -- 2的32次方-1,即没有负数部分
(8)移码=补码的符号位取反的结果
反码取反所以和原码相反,对于补码来说,先找到第一个1,他的高位取反,低位不变,所以左移时低位补齐和原码一样的0,右移的时候左边补齐和反码一样的1
2.浮点数和定点数
(1)定点数
定点小数是小数点位置固定的小数,由于表示方法的局限,精度和范围比较低,C++和C中一般用float或者double,遇到过的定点数,只有在shader中为了简化计算用到过。
(2)单精度浮点数
±1.f×2 E−127,其中,fff是尾数,EEE是指数(原文链接:https://blog.csdn.net/whyel/java/article/details/81067989)
偏移位是为了将-127 --- +127 映射到0-255,
符号位f,指数位e,尾数位t: 1+8+23
规格化表示的浮点数,整数位固定为1,可以省略,所以用23位可以存储24位的尾数,第一个1开始到最后一个1为止的总位数超过24,那么该int值就不能被float类型精确表示·
正常情况下23位尾数位,即这个数等于 f*t乘以2的e次方,那么规定t的首位为1,因为0可以省略,那么最高位必定是1,我们可以将他省略,也就是存储一个23位的尾数,且这个尾数必须以1开头,那么实际存储的可以达到24位,相当于扩展了精度,当然在运算的时候要记得这位特殊处理,如果觉得精度还是不够用,所以就产生了双精度double
指数偏移2的7次方-1,因为指数部分也要区分正负,所以8位二进制其实存储的是七位的有效数字-127` +127,
范围:(-2E128~+2E128)
浮点数范围大,运算复杂,运算时要求算术先规格化,而且结果也要规格化,所以在需要高效运算而对精度要求低的时候使用定点数运算,(3)双精度浮点数
符号位,指数位,尾数位: 1+11+52
(4)无穷大和无穷小
NaN 用于处理计算中出现的错误情况,比如 0.0 除以 0.0 或者求负数的平方根。由上面的表中可以看出,对于单精度浮点数,NaN 表示为指数为 emax + 1 = 128(指数域全为 1),且尾数域不等于零的浮点数。IEEE 标准没有要求具体的尾数域,所以 NaN 实际上不是一个,而是一族
(5)浮点数的误差
小数十进制和二进制的转换本就没有完整的对照关系,也就是很多十进制小数是无法完全转化成二进制,而且即使可以转化,可以需要的位数也远远超过了32,所以计算或者类型转换的过程中,都可能会丢失信息,精度下降。
所以说浮点数的计算很容易产生误差,运算结果有时也并非遵循常理,核心原因就是精度的不准确导致看起来没有问题的代码可能会有问题,比如帧同步时,不同客户端收到浮点数进行相同的运算,机器不同结果可能也会不同,解决方法就是不要保留过高的精度,当然如果非要保留极高的精度,那么就要花时间去研究一下怎么避免这个误差了
(6)二级制和十进制的转换
整数就比较简单了,小数的话
分数转二进制:
小数转二进制:
3.数据校验
(1)奇偶校验,通过在末尾增加一个0或者1,来确定传输后的数据奇偶性和传输前一致,当然如果数据出错的个数是偶数个,就无法查出了
(2)海明码:在1,2,4,8这些位置穿插校验位,大小要大于实际数字的最大值,比如1,2,4就是8
(3)CRC循环冗余校验
4.数据运算和溢出
有符号数和无符号数的计算结果溢出判断
溢出只会发生在同正或者同负的两个数之间,正数和负数相加永远不会溢出。相加结果溢出时,所有结果均不可靠,
1:对于有符号32位整数,范围为-2的31次方到2的31次方减1,而无符号整数由于不用多出一位来标记正负,所以范围更大,0到2的32次方减1,所以两个有符号正数相加结果用无符号整数表示一定不会溢出,可以先进行类型转换,然后判断结果是否大于有符号整数的边界
2:a+b>INT_Max,a+b的结果大于有符号整数最大值INT_MAX,变形式子,a > INT_MAX - b,因为INT_MAX一定大于b,所以用a和INT_MAX两个都没溢出的数直接作比较
3:整数的符号位都为0,负数的符号位都为1,负负得正和正正得负为溢出
5.运算及应用
位运算(直接用二进制进行运算,效率更高)
&:
(1)清零数据:将一个数和全0数据与运算,得到0
(2)取一个数的指定位:想要取的位为1其他位为0,即取到指定位
(3)判断奇偶:二进制末尾为1即为奇数,为0则为偶数
|:
(1)将数据的某些位设置为1
^:
(1)翻转某些位,0和1异或结果为1,1和1异或结果为0,将0变为1,1变为0
(2)与0异或,结果仍为自己本身
(3)交换两个数
~:
使一个数的最低位为零
使a的最低位为0,可以表示为:a & ~1。~1的值为 1111 1111 1111 1110,再按"与"运算,最低位一定为0。因为“ ~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高
<<:
x<<n,x左移n位,如果左移出的高位数字没有出现1,则相当于将x*2的n次方
6.各种数据类型
1byte,8个字节
bool:1byte
signed short(有符号短整型):2byte,范围-2的15次方 到 2的15次方减1, -32768- 32767
unsigned short(无符号短整型) : 2byte,范围0到2的16次方减一, 0 - 65535
signed int(有符号整型):4byte,范围-2的31次方到2的32次方减一,-2147483648~2147483647
unsigned int(无符号整型):4byte,范围0到2的32次方减一,0~4294967295
long(长整型):
char:1byte
float(单精度浮点数):4byte,1+8+23
double(双精度浮点数):8byte,1+11+52
7.机器语言
(1)将高级程序语言翻译成机器能识别的机器语言,一种是解释型,一种是编译型。对于编译型,只需一次翻译,源程序不变的话无需再次翻译。而对于解释型,每执行一次就要翻译一次
(2)计算机由运算器,存储器,控制器,输入设备,输出设备五大部分组成,运算器和控制器逻辑联系紧密,放在中央处理器CPU上,所以又可以说计算机由CPU,存储器,IO设备组成
8.存储器
(1)Cpu:超大规模集成电路
RAM(Random Access Memory):存储器的任何一个单元的内容都可以随机读取
ROM(Read Only Memory):只读
CPU不能访问辅存,可以直接访问寄存器,而CPU和寄存器之间还存在一种更小,速度更快的内存叫做Cache,现代计算机把Cache直接制作在Cpu内
Gb->(1024)Mb->(1024)Kb->(1024)B,, 1B(1字节) = 8bit, bit就是位,8bit就是8位二进制,64位操作系统就是8*8位
Cache命中:Cpu要访问的数据或者指令已经在Cache中,直接从Cache中取数据即可
Cache未命中:Cpu访问数据不在Cache中,而是在主存中,那么需要将该数据所在的主存字块调入Cache中,字块是主存和Cache交换数据的基本单元,主存和Cache的块大小相同,而且Cache的块数一定是少于主存的,Cpu要访问的数据已经在Cache中的比率叫做Cache的命中率
新的主存块需要调入Cache时的策略:FIFO,LRU,随机法,只有LRU能提高Cache的命中率,因为他考虑了访存的局部性原理,在一定时间内,CPU只是对主存的一部分区域进行访问
中断服务的流程:保护现场->中断服务->恢复现场->中断返回,宏观上Cpu和IO设备并行工作,其实微观上IO请求还是会造成Cpu暂时中断其他指令的执行,但高速的IO输入速度和短暂的中断,宏观上我们并不会感受到任何卡顿,但是频繁的中断Cpu还是会降低Cpu的效率,为此,人们发明了效率更高的DMA方式:IO设备通过DMA将数据和指令直接存储在主存,这个过程不需要中断Cpu,要注意Cpu和DMA同时访问主存时产生冲突,DMA采取周期性窃取一个存取周期的方式占用总线,总结来说,DMA像是加了个微型处理器,它也拥有自己的缓存,来处理IO设备,这样可以保证CPU稳定的运行,减小IO设备对他造成的影响
9.中央处理器(CPU)
10.寻址
核心原理就是扩大寻址范围,找一个中间的存储如寄存器,存储位于哪个大的地址块,然后在通过地址偏移找到确切的地址
(1)立即寻址:指令直接包含操作数
(2)直接寻址:指令直接包含操作数地址
(3)隐含寻址:操作数的地址在寄存器或者操作码中
(4)间接寻址:扩大寻址返回,便于编写程序
(5)寄存器寻址:直接指出操作数在寄存器中的位置,无需访存,速度快
(6)寄存器间接寻址:通过寄存器间接寻址
(7)基址寻址:通过基址寄存器存储间接地址
11.CPU工作原理