我如果有,为什么为了表示-1二进制,2的补使用的原因只是好奇:翻转位和添加1吗?
-1是由11111111(二进制补码)表示,而不是(对我更直观的)10000001这是与第一个位为负数标记二进制1。
免责声明:我不依赖于我的工作二进制算术!
我如果有,为什么为了表示-1二进制,2的补使用的原因只是好奇:翻转位和添加1吗?
-1是由11111111(二进制补码)表示,而不是(对我更直观的)10000001这是与第一个位为负数标记二进制1。
免责声明:我不依赖于我的工作二进制算术!
它这样做是另外不需要有任何特殊的逻辑来处理负数。 看看维基百科上的文章 。
假设你有两个数字,2和-1。 在数字代表你的“直觉”的方式,他们将是0010
和1001
,分别为(我坚持到4位的大小)。 在两个互补的方式,他们是0010
和1111
。 现在,让我们说,我想补充它们。
补除了非常简单。 您通常会添加一些数字和结尾处的进位被丢弃。 所以他们补充如下:
0010
+ 1111
=10001
= 0001 (discard the carry)
0001
是1,这是“2 +( - 1)”的预期结果是。
但是,在你的“直觉”的方法,将是更为复杂:
0010
+ 1001
= 1011
这是-3,对不对? 简单的加法不会在这种情况下工作。 需要注意的是,一个号码为负,且使用不同的算法,如果是这样的话。
对于这种“直观”存储方法,减法比另外一个不同的操作,要求上的数字附加检查可以被添加之前。 既然你最想要的基本操作(加,减等),要尽可能快,你需要存储的方式,让您使用最简单的算法可能的数字。
此外,在“直观”存储方法中,有两个零:
0000 "zero"
1000 "negative zero"
这是直观的相同数量,但在存储时有两个不同的值。 每个应用程序将需要采取额外的步骤,以确保非零值也不会负零。
有与存储整数这样另一个好处,当你需要扩展值被存储在寄存器的宽度是随着补,存储在一个8位寄存器中的4位数字是重复的问题了最显著位:
0001 (one, in four bits)
00000001 (one, in eight bits)
1110 (negative two, in four bits)
11111110 (negative two, in eight bits)
这只是一个看着小词的符号位和重复它,直到它垫更大的字的宽度问题。
随着你的方法,你需要清除现有的位,这是除了填充额外的操作:
0001 (one, in four bits)
00000001 (one, in eight bits)
1010 (negative two, in four bits)
10000010 (negative two, in eight bits)
你仍然需要在这两种情况下设置这些额外的4位,但在“直观”的情况下,你需要清除第5位为好。 它存在于每一个应用程序的最根本,最常见的操作一个一个很小的额外步骤。
维基百科说,这一切:
二进制补码系统没有要求加法和减法电路检查操作数的符号,以确定是否增加或减少的优势。 这种特性使系统既易于实施,并且能够很容易地处理精度更高的算术。 此外,零仅具有单个表示,从而避免与负零,它存在于ones'补系统相关联的细微之处。
换句话说,添加是相同的,阉羊或数量不限为负。
尽管这个问题是旧的,让我把我的2美分。
我来解释一下在此之前,让我们回到基本知识。 2的补数为1的补数+ 1。 那么什么是1的补,什么是它另外的意义。
任意n位的数字和1的补数的总和即为您可以通过这些n位表示可能的最高数字。 例:
0010 (2 in 4 bit system)
+1101 (1's complement of 2)
___________________________
1111 (the highest number that we can represent by 4 bits)
现在,如果我们试图更加1添加到结果会发生什么。 它会溢出的结果。
其结果将是1 0000
,其为0(如我们用4位数值,可(在左边的图1是一个上溢)
所以,
Any n-bit number + its 1's complement = max n-bit number
Any n-bit number + its 1'complement + 1 = 0 ( as explained above, overflow will occur as we are adding 1 to max n-bit number)
于是有人决定把1的补+ 1 2'complement。 所以上面的语句变为:任何n'bit数+其2的补码= 0,这意味着2的许多补体= - (这个数字的)
所有这一切都产生一个问题,我们为什么只能使用(N-1)的n位来表示正数的和为什么最左边的第N位表示最左边位的手段+符号(0已经数,1所表示-ve数)。 例如,为什么我们只使用在java中int的第31位来表示正数,如果第32位是1,它的一个-ve编号。
1100 (lets assume 12 in 4 bit system)
+0100(2's complement of 12)
___________________________
1 0000(结果是零,与进位1溢出)
因此(N的N + 2'complement)的系统= 0,仍然有效。 这里唯一的不确定性是2的12的补码为0100,其隐约也代表+8,比2的补系统较其它-12。
如果正数总是在自己最左侧位有0这个问题将得到解决。 在这种情况下,他们的2的补数将永远在他们的最左侧位为1,我们不会有相同的一组代表2的补数,以及A +已经位数的模糊性。
补允许加减以正常的方式来完成(像你伤口无符号数)。 它还防止-O(单独的方式来表示0,将不等于0与比较数的正常位逐位方法)。
这是简化的款项和数字的差异。 负数和积极的在2的补编纂的总和是一样的,在正常的方式总结起来。
通常执行的操作是“翻转位加1”,但有其定义,可能使理更清晰的另一种方式。 2的补是,如果你把每个位控制的2下一个功率通常无符号表示你得到的形式,只是做出最显著长期的负面。
以一个8位的值A 7 A 6 A 5 A 4 A 3 A 2 A 1 A 0
通常的无符号二进制的解释是:
2 7 * 7 + 2 6 * 6 + 2 5 * 5 + 2 4 * 4 + 2 3 * 3 + 2 2 * 2 + 2 1 * 1 + 2 * 0 0
11111111 = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255
该补的解释是:
-2 7 * 7 + 2 6 * 6 + 2 5 * 5 + 2 4 * 4 + 2 3 * 3 + 2 2 * 2 + 2 1 * 1 + 2 * 0 0
11111111 = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1
其他位没有改变原有的意义可言,并携带到7为“溢出”,而不是预期的工作,所以几乎所有的算术运算而无需修改(如其他人指出的)。 登录幅度一般检查符号位,并使用不同的逻辑。
为了扩大在别人的答案:
在补
司确实需要一个不同的机制。
所有的这些都是真的,因为补仅仅是正常的模运算,在这里我们选择减去模来看看一些数字为负。
补允许正数和负数,以加在一起,没有任何特殊的逻辑。
如果你想加1和-1使用方法
10000001(-1)
00000001(1)
你得到
10000010(-2)
相反,通过使用两个的补充,我们可以添加
11111111(-1)
00000001(1)你
00000000(0)
这同样适用于减法如此。
此外,如果您尝试从6(二正数)减去4,你可以2的补数4,并新增两个一起6 +(-4)= 6 - 4 = 2
这意味着,减法和加法正反两方面的数字都可以通过在CPU相同的电路来完成。
阅读这个问题的答案,我碰到这个评论是[编辑]。
2的0100补码(4)将是1100现在1100是12,如果我说正常。 所以,当我说正常的1100则是12,但是当我说2的补1100则是-4? 此外,在Java当1100(让我们假设4个比特现在)被存储然后它是如何,如果它是12或-4确定?? - hagrawal 07月02日16点53处
在我看来,在此评论提出的问题是很有趣,所以我想首先要改写它,然后提供一个答案,一个例子。
问题 - 系统如何如何建立一个或多个相邻字节都被解释? 特别是,该系统如何建立给定的字节序列是否是一个普通的二进制数或2的补数?
答案 - 系统建立如何解释通过一个类型的字节序列。 类型定义
实例 - 下面我们假设
char
的是1个字节长的 short
的是2个字节长 int
的和float
的是4个字节长 请注意,这些尺寸是针对我的系统。 虽然很常见,他们可以根据系统的不同。 如果你想知道他们是你的系统是什么,用sizeof操作符 。
首先,我们定义一个包含4个字节的数组,并初始化所有的人都以二进制数10111101
,对应于十六进制数BD
。
// BD(hexadecimal) = 10111101 (binary)
unsigned char l_Just4Bytes[ 4 ] = { 0xBD, 0xBD, 0xBD, 0xBD };
然后,我们读取使用不同类型的数组的内容。
unsigned char
和signed char
// 10111101 as a PLAIN BINARY number equals 189
printf( "l_Just4Bytes as unsigned char -> %hi\n", *( ( unsigned char* )l_Just4Bytes ) );
// 10111101 as a 2'S COMPLEMENT number equals -67
printf( "l_Just4Bytes as signed char -> %i\n", *( ( signed char* )l_Just4Bytes ) );
unsigned short
和short
// 1011110110111101 as a PLAIN BINARY number equals 48573
printf( "l_Just4Bytes as unsigned short -> %hu\n", *( ( unsigned short* )l_Just4Bytes ) );
// 1011110110111101 as a 2'S COMPLEMENT number equals -16963
printf( "l_Just4Bytes as short -> %hi\n", *( ( short* )l_Just4Bytes ) );
unsigned int
, int
和float
// 10111101101111011011110110111101 as a PLAIN BINARY number equals 3183328701
printf( "l_Just4Bytes as unsigned int -> %u\n", *( ( unsigned int* )l_Just4Bytes ) );
// 10111101101111011011110110111101 as a 2'S COMPLEMENT number equals -1111638595
printf( "l_Just4Bytes as int -> %i\n", *( ( int* )l_Just4Bytes ) );
// 10111101101111011011110110111101 as a IEEE 754 SINGLE-PRECISION number equals -0.092647
printf( "l_Just4Bytes as float -> %f\n", *( ( float* )l_Just4Bytes ) );
在RAM中的4个字节( l_Just4Bytes[ 0..3 ]
总是保持完全相同。 唯一的变化就是我们如何解释它们。
同样, 我们告诉系统如何通过类型对其进行解释。
例如,上述我们已经使用了以下类型的解释的内容l_Just4Bytes
阵列
unsigned char
:在纯二进制1个字节 signed char
:2的补1个字节 unsigned short
:2个字节纯二进制记数法 short
:2个字节2的补 unsigned int
:4个字节纯二进制记数法 int
:4个字节2的补 float
:4个字节在IEEE 754单精度符号 [编辑]该帖子已被user4581301评论后编辑。 感谢您抽出时间来丢弃这些一些有用的线条!
您可以从斯坦福大学看杰里凯恩教授解释两者的补充,在第二次演讲(关于2的补解释开始13:00左右)的系列讲座称为编程范式可以从斯坦福的YouTube频道来观看的。 这里的链接,以系列讲座: http://www.youtube.com/view_play_list?p=9D558D49CA734A02 。
补是因为它是简单的电路来实现,也不允许一个负零。
如果有x位的二的补将范围从+(2 ^ X / 2 + 1)到 - (2 ^ X / 2)。 一的补将从+(2 ^ X / 2)运行,以 - (2 ^ X / 2),但将允许负零(0000是等于1000在一4位1的补码系统)。
那么,你的意图是不是真的要扭转你的二进制数的所有位。 它实际上是减去它的每一个数字从1这只是一个幸运的巧合,从1周的结果在0减去1,再减去0 1结果在1所以翻转位被有效地执行这一减法。
但是,为什么你发现从1每个数字的区别? 好了,你不是。 您的实际意图是计算从具有相同的位数,但只包含1的另一二进制数给定的二进制数的差异。 例如,如果你的电话号码是10110001,当你翻转所有的位,你有效地计算(11111111 - 10110001)。
这就解释了在二进制补的计算的第一步。 现在,让我们有第二个步骤 - 将1 - 也是在图片。
加1到上述二元一次方程:
11111111 - 10110001 + 1
你得到了什么? 这个:
亿 - 10110001
这是最后的方程。 并通过开展这两个步骤,你要找到这个,最终差异:从另一个二进制数中减去了一个额外的数字和含除了在要位位置零的二进制数。
但是,为什么我们这个差别真的后hankerin'? 那么,从现在开始,我想如果你读它会更好, 维基百科的文章 。
我们进行了加法和减法只有加法运算。 我们的第二个操作数增加了除第一个操作数。 对于减法,我们2的第二个操作数的补充添加到第一个操作数。
用2的补码表示,我们不需要只减法,加法器和complementers独立的数字组件使用。
这是值得的注意,一些早期的加法机,电子计算机,前几天,减法将通过使操作者然后使用不同颜色的一套传说的每个键值(使每个键将进入九个减数量要被执行相减),然后按一个特殊的按钮将将承担一个进位计算。 因此,一个六位数的机器上,从一个值中减去1234,操作人员会打键,通常会显示“998765”,并打了一个按钮来表示取值加一个添加到正在进行的计算。 补算术很简单,就是早期的“ten's补”算术的二进制数。
由补体方法进行减法运算的优点是减少在硬件
complexity.The是不需要添加和subtraction.both加减不同数字电路的仅通过加法器进行的。
还未被这里提到二进制补码表示的一个主要优点是用二进制补码和,差,或产品的较低位是只取决于操作数的相应的位。 之所以为-1 8位带符号的值是11111111
的是,其减去最低8位是任何整数00000001
从任何其他整数,其最低8位是0000000
将产生一个整数,其最低8位是11111111
。 在数学上,值-1将是1的无限字符串,但一个特定的整数类型的范围内的所有值要么是全部为1或全部为0的过去的某一点,因此它是便于计算机“符号扩展”的一些最显著位,就好像它表示1或0的无限数量。
进行加法或减法时二进制补码差不多是只签号码表示与类型比二进制机器的自然字大小处理时效果很好,因为代码可以获取每个操作数的最低块,计算最低块的结果,和商店,然后加载每个操作数的下一个块,计算结果的下一个块,并存储等。因此,即使一个处理器,其要求所有加法和减法,以经过一个单一的8位寄存器可以合理有效地处理32位的符号数(除用32位寄存器当然,速度较慢,但仍是可行的)。
当使用C标准所允许的任何其他签名交涉,结果的每一位可能由操作数的任何位的影响,因此有必要或者在举行一次寄存器的整个价值或是按照一个额外的计算步骤,将在至少一些情况下,需要读取,修改和重写的结果的每个组块。
为什么Two2的补一个满意的答案是用来表示负数,而不是一个人的补体系统是二补数系统解决了存在于表示负的一个补数系统的0多个交涉的问题,以及需要为最终左右,携带数字。
欲了解更多信息,请访问https://en.wikipedia.org/wiki/Signed_number_representations
对于最终围绕头进行访问https://en.wikipedia.org/wiki/End-around_carry
因为CPU厂商都懒!