https://www.allaboutcircuits.com/technical-articles/fixed-point-representation-the-q-format-and-addition-examples/ 直接看原贴挺好,我复读一遍
无符号整数二进制乘法很简单,基本上就是补位到位数相同,然后乘数中的每一位与另一个乘数的每一位做AND(与)运算,然后移位累加就可以了。
那么把无符号二进制整数乘法拓展到无符号二进制小数乘法,就涉及小数格式的问题。这里说定点二进制小数格式:Qn format;小数点位于第 n 位元之右侧,称为Qn 格式。Q3.3就是3位整数3位小数。
乘数A是Qm.n整数部分m位,小数部分n位; 乘数B是Qo.p,整数部分o位,小数部分p位;那么积A*B 就是Q(m+o).(n+p),整数部分(m+o)位,小数部分(n+p)位;按照无符号二进制整数乘法进行,然后把输出从低到高按照位数划分整数和小数部分就可以得到正确的结果。
现在把无符号二进制整数乘法拓展到考虑符号的整数二进制乘法,这就涉及二进制符号位,补位的问题了。考虑符号二进制整数,最高位是符号位,1表示负数,0表示正数。负数的补码是所有位取反(反码)然后加1,正数的补码是正数本身。
1111是负数,它表示-1,它的补码是0001(反码加一后最高位溢出舍去),所以负数二进制的数值是补码视为正数的相反数。符号位权位-2^(n-1)——n为二进制数的位数,计算符号二进制数的十进制也可以用权来计算。
(1111)2=1*(-2^3)+1*2^2+1*2^1+1*2^0=-8+4+2+1=-1;
另外还需强调一点,就是符号二进制数的补位。我们都知道不同位数无符号二进制数进行运算需要在位数小的数前面补0,例如无符号数1011和100相加,变成1011和0100相加,因为显然,100和0100, 00100, 000100都是相等的,高位补0产生0*2^(n),不对原始数值有影响。
但是负数二进制数的补位是要在高位补1:直接解释,假设仅要增补1位,如果不是1就改变了负数为正数。由此递推到补n位,都是补1;也可以从权的角度来说明……
符号二进制数的计算需要考虑每个乘数分别的符号,可以分为:正数*正数,正数*负数,负数*正数,负数*负数
正数*正数:正常运算就行了,依次与然后移位累加。
正数*负数:负数的最后一位(最高位,也就是符号位)与正数乘法时,需要取反码加1然后最高位补一位1;示意图:
上图这里01001是正数,10010是负数,负数从低位开始直到最后一位之前(第3行到第6行),都是正常的与运算然后移位;当最后一位(第7行)时直接把正数取反加1 (01001 变为10111),并补一位1 (10111变为110111,因为5位*5位,应该是10位,补1补到10位)。到此再进行累加,就可以得到正数*负数的结果。
负数*正数:正常进行正数的每一位与负数与运算,然后移位排列,如果正数某一位是1,那么这次结果要在累加前高位补1;示意图:
上图这里101001是负数,100010是正数,实际上应该是1101001和0100010做乘法,但是事先声明100010是正数了。遇到正数某一位是1的情况,把这一次的结果在累加前高位补1(第4行,第8行),其余正常补0,最后累加就得到正确结果。
负数*负数:遇到被乘负数某一位有1,那么这次结果在高位补1;直到最后一位,取补码高位补0;示意图:
上图11001和10010都是负数,当被乘数10010遇到某一位是1时(第4行),把这一位的结果进行高位补1;直到最后一位,把乘数(11001)取补码(11001到00111),然后不满足位数就补0(00111到000111,5位*5位是10位,结果超过10位就溢出舍去),再累加就得到正确结果。这里建议手写一下11*11也就是(-1)*(-1)。
如果m位符号二进制整数*n位符号二进制整数,结果应该是2*max(m,n)位,高位舍去。
现在进入正题,讨论符号定点二进制小数的乘法,小数格式依然是Qn format,按照上文符号整数二进制乘法进行,然后:乘数A是Qm.n 符号位1位,整数部分m-1位,小数部分n位; 乘数B是Qo.p,符号位1位,整数部分o-1位,小数部分p位;那么积A*B 就是Q(m+o).(n+p),整数部分(m+o-2)位,小数部分(n+p)位,剩下高位都是补位的符号位;按照符号二进制整数乘法进行,然后把输出从低到高按照位数划分整数和小数部分就可以得到正确的结果。这里建议手写一下1.1*1.1也就是(-0.5)*(-0.5)。
可以直接看开头提到的原贴。