我听说C,C ++,Java使用两个补码进行二进制表示。为什么不使用1补充?使用2补语超过1补语是否有任何优势?
答案 0 :(得分:8)
使用两个补码有符号整数更加清晰。您基本上可以添加签名值,就好像它们是未签名的并且可以按预期工作,而不必明确处理额外的进位添加。检查值是否为0也更容易,因为两个补码仅包含一个0值,而一个补码允许一个定义正零和负零。
对于额外的进位添加,请考虑将正数添加到小的负数。由于一个补码的表示,当看作无符号数量时,小的负数实际上相当大。将两者相加可能会导致进位溢出。与无符号加法不同,这并不一定意味着该值太大而无法表示在一个补码中,只是表示暂时超过了可用的位数。为了弥补这一点,在将两个补码数加在一起后,将进位位重新加入。
答案 1 :(得分:7)
数字的内部表示不是任何一种语言的一部分,它是机器本身架构的一个特征。大多数实现使用2的补码,因为它使加法和减法具有相同的二进制运算(有符号和无符号运算是相同的)。
答案 2 :(得分:2)
这是一个功课问题吗?如果是这样,想想你如何在1的补体系统中代表0。
答案 3 :(得分:2)
不同语言的答案有所不同。
在C的情况下,理论上 可以在1的补码机器上实现语言...如果你仍然可以找到一个工作的补码机器来运行你的程序!使用1的补码会引入可移植性问题,但这是C的标准。我不确定C ++的交易是什么,但如果它是相同的话我也不会感到惊讶。
对于Java,语言规范规定了基元类型的精确大小和表示,以及算术运算符的精确行为。这样做是为了消除在使这些实现具体化时出现的可移植性问题。 Java设计者指定了2的补码算法,因为所有现代CPU架构都实现了2的补码,而不是1的补码整数。
为什么现代硬件实现2的补码而不是1的补码,请看一下(例如)关于这个主题的维基百科页面。看看你是否可以弄清楚替代方案的含义。
答案 4 :(得分:1)
至少C和C ++通过语言的~
运算符提供1的补码否定(与逐位否定相同)。大多数处理器 - 以及所有现代处理器 - 使用2的补码表示有几个原因:
编辑: draft of C++0x未指定有符号整数类型是1的补码还是2的补码,这意味着早期版本的C和C ++确实指定了它。您观察到的是实现定义的行为,由于性能原因,它至少是现代处理器的2补码。
答案 5 :(得分:1)
几乎所有现有的CPU硬件都使用了两个补码,因此大多数编程语言也都有用。
如果硬件提供,C和C ++支持一个补码。
答案 6 :(得分:0)
它与零和舍入有关。如果你使用第一补码,你最终可能有两个零。有关详细信息,请参阅here。
答案 7 :(得分:0)
符号幅度表示对于数字代码会好得多。缺乏对称性是2的补码的真正问题,并且还排除了许多有用的(以数字为导向)比特黑客。 2的补充还引入了特技情况,其中算术运算可能无法给出您认为可能的结果。所以你必须注意分裂,转移和否定。