第二章 计算机的数据表示
目录
数值数据的编码无非就是讨论三类问题:
1.纯整数计算机怎么存? 存补码
2 纯小数计算机怎么存? 只存小数部分,然后在之前填上符号位即可
3. 既有整数部分又有小数部分的数据计算机怎么存?
0x00 数据编码的概念
数据是计算机处理的对象
分类:
- 数值数据
- 非数值数据
数据必须经过编码才能被计算,处理,存储,传输
编码是采用少量基本符号(0,1)规定一系列组合规则来表示大量复杂的信息。
基本符号:
位:bit
最基本的存储单元
位运算:与& 或| 非^ 异或
思想:
两个数相加求全集,全集中减去自己就是对方。
异或可以理解为二进制加法。
自己异或自己=0
问题:
第一种如果两个地址相同就完蛋了
第二种如果两个数相等就完蛋了
字节:8bit
int x = 0x ff 11 22
小端系统:数值高位 放在 内存地址高位
数值地位放在 内存地址低位
大端系统:正好相反
字:2个字节或者4个字节
作业5.14
(2)
3
(3)
大端系统:
0x01 数值数据的编码
(1)定点数的存储形式:小数点固定的数
分为纯整数和纯小数
如果将小数点约定到最低位之后,那就是纯整数
并且如果约定最高位表示符号,可以表示正负。
如果没有约定最高位表示符号,则只能表示正
如果将小数点约定到最高位之前,那就是纯小数,即只能存小数点之后的数据。
如果想表示负的纯小数,则将最高位作为符号位,小数点位于符号位之后。
例如:1.100 0000(原码)就表示 -0.100 0000
表示定点数的四种编码:
1.原码:
符号数值表示法
定点小数的原码:
注意:定点小数 二进制 转 原码
(1)小数点后部分保留(没有存0的必要,不如存0的位置来存符号位)
(2)最高位填上符号位
这样在计算机中,整数 的表示形式 其实 和纯小数的表示是相同的
比如 0 000 0001 既可以看成 是+000 0001
也可以看成+.000 0001
特点:
0有两种编码:正0和负0,这会为数学运算造成问题
负数原码的码值>正数原码的码值(码值=符号位+数据位)
2.反码:
正数和0 的反码 = 原码
负数的反码 = 符号位为1 其余位 取反
特点:
- 最高位是符号位 0表示正 1表示负
- 0的反码是不唯一的,
- 负数反码的码值>正数反码的码值
3.补码:
正数和0的补码=原码
负数的补码 = 符号位为1,数值位取反+1(取反加1操作称为求补运算)
如何由负数的补码求原码呢?对负数的补码的数值位再次求补运算即可。
求补运算的特点:就像开关一样,按两次就回到原来的状态
特点:
最高位是符号位 0表示正 1表示负
0的补码是唯一的:
【-0】补=1 111 1111 +1 = 0000 0000
虽然是数值位+1,但是计算机中符号位和数值位是连续存储的,所以+1进位会影响到符号位,并且最后会溢出
符号位的扩展:
在将两个8位补码相加的时候,我们担心结果溢出,所以需要先将8位补码扩展成16位
如何将8位补码扩展成16位的补码:
将符号位扩展8位!因为最后解释16的补码的时候,将最高位解释为符号位,其余的15位是数值位,求补运算后得到真值。
而符号位后的7个1,正好在对补码进行求补运算求真值的时候
7个1全部变成0!这样得到的真值才是正确的!
注意:
-128 转化为二进制为-1000 0000
补码符号位为1 数值位=二进制的后7位 取反加1,溢出部分舍弃
所以-128的补码 = 1000 0000
1000 0000在解释的时候1解释为负
000 0000 求补运算 = 111 1111 + 1 = 1000 0000=128
所以为-128
移码:
正数和0 的移码,符号位为1 数值位不变
负数的移码,符号位为0,数值位求补运算
特点:
最高位为符号位,1表示正,0表示负
0的移码唯一 = 1000 0000
正数的码值 > 负数的码值 可以一眼看出正负数的大小,浮点数的指数用移码
移码和补码的转换:符号位取反即可
移码的本质:移码相当于将真值在数轴上移动了128位,如上图真值0移动到了真值128的位置,移动了128
作业:已完成并提交
定点整数的补码的范围的推导方法:
正数:0111 1111=+(111 1111)=127 数值位取全1最大
负数:1000 0000= -(111 1111+1)=-128数值位取全0最大
定点小数的补码的范围的推导:
(2)浮点数的编码表示:
非标准浮点数的表示:
浮点数=尾数*基数^阶数
二进制浮点数的表示形式:v=(-1)^s * F * 2^E
s用来控制正负(要么是0要么是1)。叫做 尾符
F是尾数(一般用补码,在IEEE754浮点数中用 原码来表示)
2是基数
E是阶数(一般用移码来表示)
如何将v存入计算机呢?
需要将s,f,e存起来,有了这三部分就能还原出浮点数,而公式中的-1和2已经约定好了,所以不用存
s尾符占1位(要么是0要么是1)将f对补码进行编码,将e用移码进行编码
首先,存储一个浮点数的总位数是事先固定好的,例如C语言中float是4字节,double是8个字节。
尾数f来控制浮点数的精度,尾数f位数多则这个数的精度就高
阶数e来控制浮点数的大小,阶数e的位数多则能存的浮点数的范围大
也就是说f占的位数多了,e占的位数就少了。
<1>浮点数尾数的规格化:
因为浮点数小数点可以浮动,所以浮点数有无数种表示形式
为了让浮点数有唯一的存储形式,所以需要尾数的规格化
即将尾数F的值如下限制:
因为F是用补码表示的,1/2补码表示如下(定点小数补码表示,小数点前为符号位)
注:用8位来表示纯小数,为什么-1.0的补码是1 000 0000?
因为计算机是这样处理 1 000 0000的:
首先,计算机将 1 提取出来作为符号位 表示负,
然后将 000 0000 求补运算 ,计算数值位
即 111 1111+1即 1000 0000,因为小数点在1之后
所以数值位就是1.0
<2>计算机存储浮点数的步骤:
1.十进制转化为二进制
2.对二进制的F规格化(如果是正数,应该在1/2 和1 之间,如果是负数应该在-1到-1/2之间)
3.S编码 0表示正 1表示负
4.对阶数进行编码 移码
5.对尾数F进行编码 补码
例如:V1 = 25.5存入计算机,假设指数用移码编码4位数值位 1位符号位(一共5位,最高位
为符号位,尾数用补码表示,6位数值位,1位符号位
(1)十进制转化为2进制 25.5 = 11001.1 = (-1)^ 0 *(11001.1)*2^(0)
(2)二进制形式的尾数规格化,因为是整数,所以尾数应该在0.5和1之间
(-1)^0 *(0.110011) * 2^(+5)
(3)对 S E F分别进行编码
S 0
E 原码 00101 补码 00101 移码10101
F 原码 0.110011 补码 0.110011 (计算机中存0 110 011) 计算机存储纯小数 只存小数点后的位数(没有必要存小数点前
的0,因为是默认的),然后在
最高位上添上符号位即可。 所以纯小数的原码反码补码转化
可以忽视掉写的小数点,直接看成0 110011 转化反码和补码 ,这样取反加一这些操作就和以前一样了。
(有时带上小数点容易搞乱,不知道取反加一应该怎么操作,直接去掉小数点就可以了)
V2 = -12.25
(1) V2 = -1100.01
(2)规格化 -0.110001 * 2^(4)
(3)编码(其实f就可以涵盖s,直接对f进行编码即可)
F: -0.110 001 = 1 110 001(原码) = 1 001 111 (补码)
E: 1 0100
作业:
阶码(16进制) | 尾数(16进制) | 真值(10进制) | |
最大正数 | 11 1111(+1F) | 0 1 1111 1111(+0.1FFH) | 2143289344 |
最小正数 | 10 0001(1) | 0 1 0000 0000(+0.1H = +0.5) | 1 |
最大负数 | 00 0000(-20H) | 1 0 1111 1111(-0.101H) | |
最小负数 |
11 1111(+1F) | 1 0 0000 0000(-0.200H) | -2143289344 |
(2)
注:判断一个十进制数是否能用二进制表示的方法:如果一个十进制数能写成 x*2^y的形式,那么久可以。
3.14不行,不能转化为有限的二进制
-1917=(-1)^0*(111 0111 1101)*2^(0) = (-1)*(0.11101111101)*2^(11) 尾数超过10位不能表示
<3>.105/512 =(-1)^0*()
<4>.不能
<5>不能
s | e | f | |
-1917 | 0 | 101 011 | 1 11011 11101(尾数超过了10位不能表示) |
<3>n位浮点数的表示范围:
例题:一个24位的浮点数的表示范围是多少?
e的范围:8位移码 -2^7<=E<=2^7-1
f的范围:
f是用定点小数的形式的存储的,所以小数点前的0和1表示符号位。
0.1xxxx:
+.1000... 到+.11111....
+0.5 <=F<=1-2^(-15)
1.0xxxx: -1<F<
注:
0.1怎么转10进制?0.1+0.1=1 所以0.1 = 1-2^-1
同理0.11111..后面15个1怎么转10进制呢?当然是加上0.0000...1 凑成1,所以0.11111= 1- 2^(-15)
<4> IEEE754标准浮点数的表示:
单精度扩展,C语言没有实现,一定比单精度精度高,但是不一定比双精度高
例如:
存储步骤仍然是相同的:
单精度编码:
上图(-1)是^1,写错了
754标准的规格化:
1.xxxxx 即小数点前是1,小数点后任意
754规定对f的编码:就是用真值。把小数点后抄下来即可,位数不够则在末尾补0,小数点前的1是数值,不表示符号,不存(因为是规格化好的)
754对e的编码:用移码表示
n为分配给e的长度(754规定为8位),E是10进制的e,即上文中的6
e=E+(2^(n-1)-1)
754的移码:将真值移动了127位,(原来的移码是将真值移动了128)
双精度编码:
作业:IEEE754标准的浮点数:2.22①②
以迷你精度的754浮点数为例:
s用1位表示,e用4位表示,f用3位表示,所以:e = E +(2^(4-1)-1) =E +7 即 E = e-7
f非规格化时和f规格化时:
f非规格化:小数点前是0
f规格化:小数点前是1
非规格化向规格化数的过度是平滑的
离原点越近码点约密集,离原点约远码点约稀疏。