今天在课堂上,我的计算机老师正在向我们解释(或试图解释)如何使用Two's Complement写负数二进制数。我的问题是这样的:

最终用户如何确定11101100为236和-20之间的差异?我知道您始终可以检查最高有效位,但这始终是100%准确的吗?是否使用负二进制数的惯例来让最高有效位指示符号?

边注:
当我们可以做到时,为什么要学习二进制减法:


将二进制转换为拒绝->减去拒绝->重新转换为二进制

最佳答案

问题1:

“是否使用负二进制数的惯例来让最高有效位指示符号?”

有多种方法可以用二进制表示负数。最常见的是您正在学习的二进制补码表示形式。在该系统中,是的,最高位将指示数字的符号(如果0与正数分组)。
在标准的无符号二进制中,数字由位置表示法中的位序列表示(为简便起见,我将仅使用三个位):

b2b1b0 = 22b2 + 21b1 + 20b0 = 4b2 + 2b1 + b0
1112 = 710
1102 = 610
1012 = 510
1002 = 410
0112 = 310
0102 = 210
0012 = 110
0002 = 010

补码
看2s补码有几种方法,我认为答案在所有方法中都是显而易见的。获取此系统的一种方法是获取无符号数字的前半部分(所有数字均已设置高位)并将其移到零以下:

0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -110
1102 = -210
1012 = -310
1002 = -410

您可以清楚地看到高位指示符号。同样,0占据4个正表示形式之一,这导致范围不对称:[3,-4](尽管有时最负的值被认为是特殊的,从而使可用范围对称)。同样,我们可以将最高位重新解释为负数:

b2b1b0 =-(22)b2 + 21b1 + 20b0 = -4 b2 + 2b1 + b0

显然,由于高位的权重(就绝对值而言)比所有其他位的总和更大,因此,如果将其置位,则结果为负。如果未设置,则所有剩余权重均为正,因此结果也为正。
从这个定义中,我们可以得出第三种解释:-a = ~a + 1的众所周知的规则(其中-表示算术求反,~表示按位补码,而我们忽略了溢出):

a +〜a = -4b2 + 2b1 + b0 + -4(〜b2)+ 2(〜b1)+〜b0
a +〜a = -4(b2 +〜b2)+ 2(b1 +〜b1)+(b0 +〜b0)
a +〜a = -4(1)+ 2(1)+(1)
a +〜a = -1
a =-(〜a + 1)
-a =〜a + 1

在这里,我们看到“否定”会翻转高位,因此它表示数字的符号。请注意,这并不是严格意义上的,因为如果所有其他位都置1,则加一个可以将高位向后翻转。但是,只有0和最大负数(在这种情况下为-410或1002)才是这种情况,当取反时,两者都保持相同。
使用2s补码的好处是可以使用相同的硬件进行有符号和无符号加法。这个不错的属性不适用于过去使用的其他负数二进制表示形式,我将简要介绍其中的一些。由于这个事实,现代CPU几乎总是将这种表示形式用于整数算术(我不知道最近有任何商业反例,但它们可能在那里)。这就是为什么要学习它的原因(与Convert binary to denary -> subtract denary -> reconvert into binary相对):了解操作如何在ALU的门级进行。
补体
1s补码与2s补码密切相关。求反仅通过反转位(不加1)来执行。前导位仍指示符号,但是对于正零和负零有不同的表示形式。我从来没有亲自遇到过现实中使用1s补码的情况,但是它具有历史意义。

b2b1b0 = -3b2 + 2b1 + b0
0112 = 310
0102 = 210
0012 = 110
0002 = 010
1112 = -010
1102 = -110
1012 = -210
1002 = -310

符号和大小
符号和幅度最接近人类正常写负数的方式。低两位的权重与上述系统中的权重相同,而高位没有(加法)权重。相反,它仅更改结果的符号。显然,这里的前导位表示符号。像1s补码一样,有两种表示形式的0。今天,它仍在IEEE浮点数的尾数中使用(尽管指数位于符号和幅度之间)。

b2b1b0 =(-1)b2(2b1 + b0)
0 11 2 = + 3 10
0 10 2 = + 2 10
0 01 2 = + 1 10
0 00 2 = + 0 10
1 00 2 =-0 10
1 01 2 =-1 10
1 10 2 =-2 10
1 11 2 =-3 10

过量
Excess -n实际上更像是一个系统系列。所有值都将上移n(称为偏置),然后在无符号情况下表示。如果选择了正确的偏置,则前导位可以指示符号,尽管极性与上述系统的极性不同(并且0可以与负极或正极分组在一起)。在IEEE浮点数的指数中仍使用此方法。对于n = 3,高位确实指示符号,并且0与负数分组:

b2b1b0 = 4b2 + 2b1 + b0-n
1112 = 410
1102 = 310
1012 = 210
1002 = 110
0112 = 010
0102 = -110
0012 = -210
0002 = -310

其他
还有其他更深奥的整数表示形式,例如平衡三进制,基数负2或(可以说)二进制编码的十进制(或简称BCD)。我说BCD之所以有争议,是因为现代处理器通常仍然支持它(尽管这不是内部数字表示的方式),并且很多计算器都以此为基础。在这些系统中,前导位(或trit或base-n位)可能会或可能不会指示符号(或在某些情况下可能会指示它,但在其他情况下则不会)。
问题2:

“最终用户如何确定11101100为236和-20之间的差异?”

通常,无法像其他人指出的那样,无法分辨存储在寄存器或存储器中的数字实际上是2s补码还是无符号。从本质上讲,您必须跟踪使用它进行的操作才能确定这一点。
但是,如果数字是直接存储在机器代码指令中的立即数,则操作码可以指示其是否已签名(取决于体系结构)。例如,这可能会更改如何处理溢出或是否执行符号扩展。
例如,可能存在单独的“立即加载”和“立即加载带符号”指令,这些指令将立即值复制到更大的寄存器中,第二个执行符号扩展,第一个不执行符号扩展。 “分支”指令通常具有带符号的立即数,以指示跳转的大小(以便向前和向后的分支都可以使用单个指令)。可能存在不同的“立即添加”和“立即添加未签名的”指令,这些指令会针对添加类型适当地设置溢出标志。
标志扩展
符号扩展意味着复制高位以保留2s补码的值。对于一半的无符号数字,这将产生不正确的结果。
未执行标志扩展:

1002 = 000001002
无符号的:410 = 410
签名:-410 = 410

签署扩展名:

1002 = 111111002
签名:-410 = -410
无符号的:410 = 25210
0012 = 000000012
已签名和未签名:110 = 110

溢出
将两个数字相加或相减可能会得出太大的结果(从绝对意义上来说)而无法正确表示。相同的两个二进制序列的加法可能导致有符号数溢出,但不是无符号数(反之亦然)。
签名溢出但未签名不会:

0112 + 0112 = 1102
签名:310 + 310 = -210
无符号:310 + 310 = 610

未签名溢出但已签名没有:

1112 + 0102 = 0012
无符号:710 + 210 = 110
签名:-110 + 210 = 110

关于binary - 负二进制检测,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16488435/

10-10 18:23
查看更多