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

定点小数的机器级表示

前面讨论过用无符号整数码补码表示整数,如果约定这两种码的固定位置有小数点,那这两种码也能表示这种数,称为定点数(定点小数)。这样一来整数就是定点小数的特例,整数可看作是小数点在最低位右边的定点小数。一般来说可以约定小数点在最高位之前(纯小数)最低位之后(整数)的任意的\(k+1\)个位置上。

定点整数和数学中整数的区别不大,除了不能处理无穷。但定点小数和数学中的小数则有区别,定点小数的取值范围更像“以二进制0.1(\(2^{-1}\))、0.01(\(2^{-2}\))…为步长的整数”。比如1个4位的码1111,将其看作无符号整数码,表示15。将其看作小数点定在第2位之前的无符号小数码,表示\(15\times 2^{-2}\)。虽然计算机不直接存储小数点位置,为方便也可写作11.11。

 

定点小数的加减法

直观从竖式的角度看,定点小数可完全照搬整数加减法。这里稍微形式化的再讨论一下,首先是无符号定点小数。设\(a,b\)在\(k\)位无符号定点小数码的取值范围内,其中小数点位置在第\(i\)位前(\(i=0\)表示整数,\(i=k\)表示纯小数)。那么如果把这\(k\)位看作无符号整数码,然后做加减运算,根据前面的讨论,把结果看作无符号整数码时其表示\((a\pm b)\cdot 2^i~mod~2^k\),所以将这\(k\)位看作定点小数就是\(((a\pm b)\cdot 2^i~mod~2^k)\cdot 2^{-i}\),显然是正确的。这是无符号定点小数加减法的数学表述。

对于补码定点小数,则和补码整数一样,只要\(a,b,a\pm b\)都在某种定点小数补码的取值范围内,那么把加减法的结果看作这种定点小数补码时,其一定能够表示\(a\pm b\)。这里不去分析细节了。

 

定点小数的乘法

回顾小数乘法竖式,其步骤是先不管小数点,按整数做乘法,最后为积加上小数点,小数点位置是被乘数和乘数小数点位数的和。由于小数点后的非0最低位后面可去掉/加上任意个0,竖式为了方便都省略这些无意义的0。

然后考虑用前面讨论过的无符号整数乘法来实现这种小数乘法,由于计算机使用固定位数,所以小数点后的非0最低位后的空位都认为是补0的,比如对于小数点在第\(i\)位前的\(k\)位无符号小数码(\(i=0\)即表示整数),由于乘数和被乘数的小数点位置都确定,所以积的小数点位置也就确定为在\(2i\)位前。

从上述结论可以发现一个问题就是对于“乘数、被乘数、积都是\(k\)位的整数乘法”,可能最后积的小数点位置“越界”了。比如对于小数点在第3位前的4位无符号小数码,其计算0.1*0.01的过程是先计算0100和0010两个码的无符号整数乘法,得到1000码,最后需要补上小数点,但小数点在第6位,码一共就只有4位。这时就只能“约定”在1000前面加上两个00,并把小数点放在最高位之前,“得到”的是.001000,也就是小数0.001。

到这里就知道前面讨论整数乘法时,为什么要提到一种“乘数、被乘数是\(k\)位,积是\(2k\)位的整数乘法”,这是因为这种乘法在用于整数时能防止溢出,在用于小数时还能防止小数点“越界”。在这种乘法下,如果乘数和被乘数的码需要被当作无符号小数,只要记得最后得到的积隐含了一个小数点,位置在\(2i\)位之前。

最后对于补码小数,由于小数点和“数值位”无关,只表示要额外乘\(2^{-i}\)。所以照搬前面讨论的补码整数乘法即可。但对于“乘数、被乘数、积都是\(k\)位的乘法”,则不能像无符号小数“假想”在前面补0以得到足够的小数位,而是“假想”在前面按符号扩展方式补位。比如在小数点在第3位前的4位小数补码下(数值位只有3位所以此时是纯小数),二进制乘法0.001*(-0.001)就是0001和1111两个码的乘法,得到的是1111码,符号扩展3位(多扩展1位符号位)后是1111111,也就是小数点在第6位前的7位小数补码表示下的-0.000001。而对于“乘数、被乘数是\(k\)位,积是\(2k\)位的整数乘法”,则不需要这么麻烦。

 

定点小数的除法

 

发表评论

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

滚动至顶部