浮点数的机器级表示与算术运算(没写完)

浮点数的机器级表示

486a61c7-dd62-4ab7-9eba-e5713cce3abc(1)

440c5907-c75e-4b43-98ad-38520c15602a(2)

前面讨论的都是定点数,其特点是小数点位置静态不可变,且小数点位置本身没有硬件来存储。浮点数则是完全不同的结构,因为每个浮点数必须记录自身小数点的位置,“浮点”这个名字就是是指小数点位置可变。于是设计浮点数的表示方案会更复杂,而且小数的数学性质本身也更复杂一些,比如前面讨论过,小数进制转换天生就有精度丢失问题。

目前权威的浮点数方案是数值专家William Kahan主导的IEEE754,采用科学记数法以\((-1)^s\cdot M \cdot 2^N\)计数,科学记数法中的基数指数在IEEE754中称为尾数阶数。在计算机中会从高位到低位存储\(s,N,M\),对\(s,N,M\)的具体规定如下:

1) \(s\):符号位,表示浮点数的符号,规则是0正1负;

2) \(M\):即尾数(指小数的尾数)

3) \(N\):即阶码,这里是2的幂;

其中最常见使用的IEEE754浮点数是如下2种规范的:

1) 32位浮点数(float):共32位,从高到低为1位符号,8位阶码,23位尾数;

2) 64位浮点数(double):共64位,从高到低为1位符号,11位阶码,52位尾数;

根据阶码位的值,float/double又可被分为如下3类。上图(1)给出3类中更细分的情况:

1) 规格化浮点数阶码位不全是0、且不全是1。此时阶码表示有符号整数,但阶码不使用原码/补码/反码,而是移码(偏置码)表示法,该法以无符号整数码为基础,减去固定的正整数偏置量。偏置量大小规定为\(2^{k-1} – 1\)(\(k\)为阶码位数),比如float和double的偏置量为\(2^{8-1}-1\)和\(2^{11-1}-1\)。考虑到偏置量的存在,以及不能取全0和全1,规格化的float和double的阶码的取值范围分别是-126~127和-1022~1023。尾数位\(b_{k}b_{k-1}b_{k-2}…\)表示二进制小数\(1.b_{k}b_{k-1}b_{k-2}…\);

2) 非规格化浮点数阶码位全是0。此时尾数位\(b_{k}b_{k-1}b_{k-2}…\)则表示二进制小数\(0.b_{k}b_{k-1}b_{k-2}…\)。如果尾数位的所有位都是0,那么此时浮点数表示0,由于符号位的存在,0有-0和+0两个码。另外全0的阶码的值不是\(-(2^{k-1} – 1)\)(其中\(k\)为阶码位数),而是规定为\(1-(2^{k-1} – 1)\)。比如全0阶码的float表示-126而非-127;

3) 特殊浮点数阶码位全是1。此时尾数位全0表示正无穷负无穷,尾数位不全为0表示“这不是一个数”,也就是程序员常见的NaN类型。这出现在譬如“正无穷-正无穷”这样的在数学中也无法处理的情况;

这里看种4位阶码、3位尾数的8位浮点数的例子,具体如上图(2)。可以发现\((0,\frac{1}{512})\)和\((\frac{8}{1920},\infty)\)这两个区间的数完全无法表示,这分别被称为浮点数的正下溢区正上溢区,由于浮点数的表示范围是对数轴对称的,所以对于负数的\((-\frac{1}{512},0)\)和\((-\infty,-\frac{8}{1920})\),则分别称为负下溢区负上溢区

大多数时候\(k\)位移码都默认以\(2^{k-1}\)为偏置量,因为此时移码补码之间有特殊的关系,比如把两数的移码做加/减法,得到的结果刚好能看做两数的和/差的补码。但在IEEE规格化浮点数中,阶码的偏置量是\(2^{k-1}-1\)。其目的可能是让浮点数的范围更对称,比如float采用127偏置量时,其大致范围是\((1.2\times 10^{-38}, 3.4\times 10^{38})\),采用128偏置量时是\((5.9\times 10^{-39}, 1.7\times 10^{38})\),前者更对称。而非规格化阶码全0浮点数的偏置量之所以为\(1 – (2^{k-1}-1)\),是为了和规格化浮点数平滑过渡,如上图的编码能实现最大非规格化值\(\frac{7}{512}\)到最小规格化值\(\frac{8}{512}\)的平滑过渡。

 

整数移码的加减法

浮点数乘除法需要做阶码加减,即偏置量\(2^{k-1} – 1\)的\(k\)位移码整数的加减,这种移码的表示范围是\([-2^{k-1}+1,2^{k-1}]\)。设\(a,b\)在该移码取值范围内,其移码分别可看作\(a + 2^{k-1} – 1, b + 2^{k-1} – 1\)的无符号整数码。这表明如果按无符号整数的方式直接计算移码,会多带上1次偏置量,从而导致结果错误。

1) 加法:先让\(a,b\)移码直接按无符号整数相加,结果在看作无符号整数时表示\((a+b+2^k-2) ~mod~2^k\)。再让该结果按无符号整数的方式减\(2^{k-1} – 1\)对应的无符号整数码,得到\((((a+b+2^k-2) ~mod~2^k) – ((2^{k-1} – 1)~mod~2^k))~mod~2^k \)的无符号整数码。使用余数加法定理,等于\((a+b+2^{k-1}-1)~mod~2^k\)。即若\(a+b\)在该移码表示范围内,则该结果是正确移码。

2) 减法:首先当作无符号整数做减法,得到的结果看作无符号整数时表示\((a-b) ~mod~ 2^k\)。再将该结果按无符号整数的方式加\(2^{k-1} – 1\)对应的无符号整数码。最终得到的结果看作无符号整数码时表示\((a-b+2^{k-1}-1)~mod~2^k\)。即若\(a-b\)在该移码表示范围内,则该结果是正确移码。

 

小数原码的加减法

可以把浮点数中的尾数和符号位一起看成类似原码的结构,浮点数算术运算要做这部分的算术运算,所以可以先讨论整数原码加减法。但这里不妨先讨论无符号定点小数加减法,这部分之前在讨论无符号整数时没有讨论,因为从直观上,无论小数点定在什么位置,照搬无符号整数的加减法就能得到正确结果。

如果一定要用数学的方式来表述无符号定点小数加减法,可以先设被加/减数、加/减数分别为\(a,b\)。其在小数点在\(i\)位(\(i=0\)即是整数)的\(k\)位码的取值范围内,

 

因为从竖式的角度来看,由于计算机中的数是固定位数的,所以两数的位数是一样的,

 

可发现减法的最简单处理方式是预先做一步减数符号位取反,再做原码加法即可。所以这里只需讨论原码加法的具体步骤:

1) 两数原码符号位相同:把数值位当作无符号整数码做加法,溢出位舍弃。把符号位设定为被加数/加数的符号位,这样无论数值位是否正确(溢出),符号位都是正确的;

2) 两数原码符号位不同:第一步是按无符号整数码的方式,把正符号位原码(设其表示的值为\(a\))的数值位减负符号位原码(设其表示的值的绝对值为\(b\))的数值位,溢出位舍弃。根据前面对无符号整数运算的讨论,得到的结果的数值位在被看作无符号整数时,表示的是\((a-b)~mod~2^{k-1}\)。接下来的步骤需要分情况讨论:

2.1) \(a-b\geq 0\):此时\((a-b)~mod~2^{k-1} = a-b\),数值位是正确的结果。符号位应取正数0;

2.2) \(a-b<0\):此时\((a-b)~mod~2^{k-1} = 2^{k-1}+a-b\),数值位是由于“不够减”导致的错误结果,但如果对数值位做一次“按位取反+1”,那么新的数值位在看作无符号整数时,表示的是\(b-a\)。进而最终结果的符号位应当取负数1;

简单考虑一下小数点定在任意位置的原码的加减法,小数竖式要求两数小数点对齐(整数竖式可看作小数点在最右所以是最右对齐的),由于计算机中数的位数是固定不变的,所以最右对齐按小数点对齐的效果相同,所以最后得到的都是一样的。也就是原码小数和原码整数的加减法是一样的。

如果一定要把原码加减法用数学表述,可以这样表述,设被加数(被减数)和加数(减数)为\(a,b\),其在小数点定在从右到左第\(i\)位(\(i=0\)是整数,\(i=k-1\)是纯小数)的\(k\)位原码的取值范围内。那么上述原码加法的结果是\((a\times 2^i + b\times 2^i) ~mod~2^{k-2}\)。

那么在\(k\)位原码

 

原码的乘法

146c98fe-8030-4f1c-9d69-9efa11f9c068

先分析原码整数的乘法,数值位可通过两数原码数值位做无符号整数码乘法得到,符号位则取两数符号位的异或。这样在\(k\)位原码下,把被乘数和乘数计为\(a,b\),结果表示\(\frac{ab}{|ab|}(|ab|~mod~2^{k-1})\),即正确的符号位和可能“溢出过”的数值位。

由于浮点数尾数是表示小数的,所以还要分析原码小数的乘法,这里分析之前讨论无符号整数乘法时没有顺带讨论的无符号定点小数乘法。这里规定小数点可以在最高位之前(纯小数)和最低位之后(整数)的任意位置。

 

原码小数乘法和无符号定点小数乘法差不多。这里就分析之前讨论无符号整数乘法时,没有顺带讨论的无符号

虽然之前没讨论过其他“码”在用于表示定点小数时的算术运算方法,但其和整数差别不大。还是从小数竖式的角度分析,

 

原码乘法和无符号整数乘法基本差不多,符号位取被乘数和乘数符号位的异或,数值位大致上按无符号整数乘法的方式计算即可。由于浮点数尾数是定点小数,所以还要考虑原码小数的情形。

 

原码的除法

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部