当我们对2的补码数进行乘法时,我很难理解为什么我们丢弃MSB。
让我们以101
(十进制:-3)和011
(十进制:3)为例。算法是这样的:首先我们将数字的长度加倍,然后我们像在学校那样用小数进行通常的乘法,然后我们采用(加倍长度)* 2 = 6个最低有效位。
双倍长度:
101 -> 111101
011 -> 000011
做乘法:
111101 * 000011 = 10110111
(十进制:-73)
如我们所见,这个结果是错误的。
10110111 -> 110111
(十进制:-9)所以结果变得非常正确。怎么解释这个?我知道MSB有点特殊,我在学校使用的规则不能100%适合2的补充,但是虽然我完全理解学校的乘法规则,但我无法绕过2的最后一步。补码乘法(我理解前两步)。
答案 0 :(得分:5)
你的乘法是不正确的。你做了一个无符号乘法。换句话说:
111101
000011 x
------
111101
111101
000000
000000
000000 +
----------
0010110111
或者在十进制61 x 3 = 183.但是有符号乘法也需要扩展部分乘积中的符号位。像这样:
111101
000011 x
------
1111111101
111111101
00000000
0000000
000000 +
----------
1111110111
所以现在你正确计算-3 x 3 = -9。这种区别对处理器也很重要,比较英特尔处理器上的MUL与IMUL。
答案 1 :(得分:1)
这只是关于算术的。它在语义上不是错误的,因为它实际上是一个正确的modulo结果,因为对计算机中整数的操作会导致丢弃高位,这类似于k位计算机中的模2 k
首先,您应该知道非加宽乘法对于无符号和2的补码有符号数具有相同的位模式。
例如:1001 2 x 0011 2 。
- 作为无符号处理我们有9 x 3 = 27(0001 1011 2 )
- 将它们视为签名我们有-7 x 3 = -21(1110 1011 2 )†
您可以看到特定案例here。对于一般情况,例如,取2个正 k位数字m
和n
。这意味着它们的负值-m
和-n
将由2 k - m和2 k - n §分别。现在我们将这2个负值相乘得到 k-bit 结果:
( - m)( - n)mod 2 k
=(2 k - m)(2 k - n)mod 2 k
= [2 2k -2 k (m + n)+ mn] mod 2 k
= mn mod 2 k
=( - m)( - n)mod 2 k
如果一个数字为正数而另一个数字为负数
,则相同因此,无论将两位模式视为有符号还是无符号,结果仍然相同。
现在我们有两个 n位无符号数并对它们进行乘法运算,我们将得到 2n 位数,因为乘以n位数和m位数产生(n + m)位结果。
但是如果我们只关心结果的低n位那么它与具有相同位模式的两个n位无符号数的结果完全相同,如上所述。< / p>
所以我们取两个(n / 2)位有符号数,将它们符号扩展为n位(你的1 st 步骤)并进行非加宽乘法(你的2 nd 步骤)获得n位结果。我们现在拥有的是与从n / 2位到n位的带符号加宽乘法完全相同。
将已签名操作数中的位加倍实际上只是使它们与最终结果一样宽,这样乘法现在是无符号非加宽,而不是像之前那样有符号扩宽。
† 如果你注意到,如果你看一下上面的证据,那么有符号和无符号版本的高位也会相互关联
§ 因为two's complement的定义是这样的:
N位数的二进制补码定义为complement相对于2 N ;换句话说,它是从2 N
中减去数字的结果
类似于1的补码和二进制的2的补码,在十进制中我们有9's complement and 10's complement来表示负数,虽然它没有在日常生活中使用并且超出了这个问题的范围
答案 2 :(得分:0)
乘法只是重复添加。
当我们将两个 n位数相加时,结果有(n + 1)-bit ,因为最多可以有一个携带MSb。
当我们将两个 n位数相乘时,结果为(n + n)-bit ,因为我们最多为自己添加一个数字 n 时间,最多产生2个 n ,并且 log 2 (2 n )= n 位。
由于我们通过添加 2n-bit 数字来工作,我们需要签名将操作数扩展到其大小的两倍。
当增加两个补码的大小时,这是一个标准规则。
如果我们使用这种效率低下的算法,我们不需要丢掉任何东西。
将 a 和 b 与 b = b k 相乘的小学校验算法 b k-1 ... b 1 b 0 将分配属性利用为 a * b = a * b 0 < / em> + a * b 1 * B + a * b 2 < / sub> * B 2 + a * b 3 * B 3 < / sup> + ...其中 B 是数字的基础。
这很有用,因为二进制数字 b i 为0或1,因此可以添加一个数字(如果 b i < / sub> = 1)或者它不是(如果 b i )= 0)。此外,幂 B i 是2的幂,因此它们可以实现为移位。
现在,由于最终结果 a * b 必须至少 2n-bit 每个加数 a * b i * B i 的大小必须 2n-bit 。
(再次在你的问题中解释得很清楚)
但是,当我们使用移位来执行乘法 B i 时,会引入超出 2n 所需的额外位。
例如:
|
111 111
| 011
-------
| 11
| 11
| 11
|11
11
11
|
这些比特只是这样一个事实:作为人类,在我们完成所有总和而不是在每个总和中,在我们到达之后停止剩余的比特更简单。 2n -th bit。
在实际硬件中执行后者,它们具有 2n-bit 寄存器,在那里它们扩展操作数,并且在移位期间,剩余位被丢弃(就像正常移位一样)。 累加总和的寄存器也会丢弃进位(就像普通加法器一样)。
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
|000 011| + |000 110| + |001 100| + |011 000| + |110 000| + |100 000|
+-------+ +-------+ +-------+ +-------+ +-------+ +-------+
=
+-------+
|111 101| Correct result with no bits discarded (but for the sums carries)
+-------+