二进制编码
1,整数的二进制表示,最左侧0代表正1代表负,正数用原码表示,负数用补码表示。
2,英文字符、数字、特殊符号用8位二进制表示,即ascii码。
1)ascii码表示数字文本形式,比整数的二进制表示多占用空间,整数、浮点数采用二进制序列化比文本节省空间。
2)ascii只表示了128个字符对于不同语言是不够用的,unicode字符集则包含了150种语言的14万个不同的字符,可以用UTF-8、UTF-16、UTF-32的字符编码存储成二进制。
3,文本采用一种编码存储,必须使用同样的编码解码,否则就会出现乱码。
1)如果采用unicode字符集记录遗留老字符集内的文本,这些字符在unicode字符集中不存在,unicode会统一把字符记录为U+FFFD,如果采用UTF-8的格式存储,就是\xef\xbf\xbd,如果连续两个这样的字符存放在一起\xef\xbf\xbd\xef\xbf\xbd,再用GB2312的方式decode,就会变成“锟斤拷”,此为使用GB2312的编码格式解密UFT-8的格式的文本。
2)如果使用Visual Studio的调试器,默认使用MBCS字符集,0xCC为未初始化内存的值,多个未初始化内存的值为\xCC\xCC,使用GB2312编码格式解码则会显示“烫烫烫”。
4,程序最终执行的是二进制的机器指令,即0或1的二进制代码。
1)在电信号传输中线路过长而导致电阻大增信号衰减,同时无法长距离传输信号,在电路中增加继电器设备,中继不断通过新的电源重新放大已经开始衰减的原有信号。
2)基本的逻辑电路,通过继电器或中继,可进行长距离的信号传输,通过设置不同的线路实现更多不同信号表示和处理方式,这些路线的连接方式就是数字电路中的门电路。
3)门电路是创建CPU和内存的基本逻辑单元,通过千万个晶体管组合在一起表示0和1的状态。
5,通过电路在计算机硬件层面设计最基本的门电路单元,如与门、或门、非门/反向器、或非门、异或门、与非门。包含十亿级别晶体管的现代CPU就是由这些基本门电路组合而成的。
浮点数的表示
1,采用二进制表示十进制的编码方式叫BCD编码(Binary-Coded Decimal),32bits可以表示40亿个不同的整数。
2,4bits可以表示0~9的整数,则32bits可以表示8个0~9的整数,如果把最右边2个0~9的整数当成小数部分,把左边6个0~9的整数当成整数部分,则32bits可以表示0~999999.99的1亿个实数了。
1)BCD编码的小数点固定在某一位的方式,称为定点数。
2)但这样表示的实数范围较小,且不能表示无穷大数和无穷小数。
3,计算机中用科学计数法表示浮点数有一个IEEE的标准,一个是32bits表示的单精度浮点数,一个是64bits表示的双精度浮点数。
1)单精度的32bits分为三部分,第一位是符号位表正负用s表示,浮点数都是有符号的。接下来8bits组成的指数位用e表示,指数位也有正有负,将1~254映射到-127~127范围内的数,1~127代表负数(-127\~-1),128~254代表正数(1~127),0和255留用。最后是23bits的有效数位用f表示,浮点数可表示为s1.f*2e。
2)浮点数要表示0或一些特殊的数,需要使用e上留下的0和255。
3)e为0,f为0,浮点数为0。
4)e为0,f不为0,浮点数为0.f,
5)e为255,f为0,s为0,表无穷大。
6)e为255,f为0,s为1,表无穷小。
7)e为255,f不为0,表NAN。
8)这样的表示方式浮点数范围大了很多(不考虑符号的话差不多是1.17*10(-38) ~ 3.40*1038)。
9)指数位e的值不同小数点的位置也不同,所以称为浮点数。
4,十进制浮点数表示成符号位s+指数位e+有效位数f的二进制,有效位数f有位数的限制,表示成二进制后会有精度损失。
1)浮点数的加法,先对齐再计算,先对齐指数位,把两数指数位统一成较大的一个,较小指数位统一成较大的指数位则有效位相应左移,右侧的有效位丢弃,加法之前,丢失精度。如果两数相差巨大,则相加后结果可能无变化。
2)在一些积少成多的场景,丢失的精度累积够多的话则会影响计算结果,比如机器学习中,计算海量样本的梯度或loss,会出现几亿个浮点数的相加,每个浮点数差不多大,但累积值越来越大就会出现大数吃小数的情况。
3)加法运算中精度损失可使用Kahan Summation算法,Kahan Summation的算法在每次计算过程中,先用一次减法把当前加法计算中损失的精度记录下来,在后续加法循环中把精度的损失放到要加的小数上,再做一次运算。
5,浮点数表示法,虽然表示的数据范围大了很多,但存在精度损失的问题,在实践应用中,对于需要精确数值的,如银行存款、电商交易等使用定点数或整数类型。