我只是好奇,为了在二进制中表示-1,是否有一个原因,使用了2的补码:翻转位并加1?
-1由11111111(2的补码)表示,而不是(对我来说更直观)10000001,10000001是二进制1,第一位为负标志。
免责声明:我的工作不依赖二进制算术!
我只是好奇,为了在二进制中表示-1,是否有一个原因,使用了2的补码:翻转位并加1?
-1由11111111(2的补码)表示,而不是(对我来说更直观)10000001,10000001是二进制1,第一位为负标志。
免责声明:我的工作不依赖二进制算术!
当前回答
用补法执行减法的优点是减少了硬件 的复杂性。不需要不同的数字电路来进行加减法运算 加法和减法只能由加法器执行。
其他回答
2的补语允许负数和正数相加,而不需要任何特殊的逻辑。
如果你想用你的方法做1和-1相加 10000001 (1) + 00000001 (1) 你得到 10000010 (2)
相反,通过使用2的补数,我们可以相加
11111111 (1) + 00000001 (1) 你得到 00000000 (0)
减法也是如此。
同样,如果你试着用6减去4(两个正数),你可以用2补4,然后把两者相加6 + (-4)= 6 -4 = 2
这意味着正数和负数的减法和加法都可以由cpu中的同一个电路完成。
在阅读这个问题的答案时,我看到了这条评论[编辑]。
0100(4)的补数是1100。现在1100是12如果我说正常的话。所以, 当我说标准1100时,它是12,但当我说2的补足1100时,那么 是-4?另外,在Java中,当1100(假设现在是4位)被存储时 如何确定它是+12还是-4 ?——hagrawal 7月2日16:53
在我看来,这条评论中提出的问题非常有趣,所以我想首先重新措辞,然后提供一个答案和一个例子。
系统如何确定一个或多个相邻字节必须如何解释?特别是,系统如何确定给定的字节序列是普通二进制数还是2的补数?
ANSWER -系统建立如何通过类型解释字节序列。 类型定义
需要考虑多少字节 如何解释这些字节
示例-下面我们假设
Char的长度为1字节 短的是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 ) );
未签名的空头和空头
// 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 ) );
内存中的4个字节(l_Just4Bytes[0..]3)始终保持完全相同。唯一改变的是我们如何理解它们。
同样,我们告诉系统如何通过类型来解释它们。
例如,上面我们使用了以下类型来解释l_Just4Bytes数组的内容
无符号字符:纯二进制的1字节 有符号字符:2的补码中的1字节 无符号短:2字节的纯二进制表示法 短:2字节的2补码 Unsigned int: 4字节的纯二进制表示法 Int: 4字节的2的补码 float:在IEEE 754单精度表示法中为4字节
[编辑]这篇文章是在user4581301的评论后编辑的。谢谢你抽出时间来写这些有用的句子!
为什么用Two2的补语系统来表示负数,而不是用One的补语系统,一个令人满意的答案是 二的补语系统解决了一的补语系统中存在的表示负数的0的多重表示和对进位的需要。
欲了解更多信息,请访问https://en.wikipedia.org/wiki/Signed_number_representations
用于末端绕行访问 https://en.wikipedia.org/wiki/End-around_carry
这是为了简化数字的和和和差。2的补数中一个负数和一个正数的和与正常方式的和是一样的。
A major advantage of two's-complement representation which hasn't yet been mentioned here is that the lower bits of a two's-complement sum, difference, or product are dependent only upon the corresponding bits of the operands. The reason that the 8 bit signed value for -1 is 11111111 is that subtracting any integer whose lowest 8 bits are 00000001 from any other integer whose lowest 8 bits are 0000000 will yield an integer whose lowest 8 bits are 11111111. Mathematically, the value -1 would be an infinite string of 1's, but all values within the range of a particular integer type will either be all 1's or all 0's past a certain point, so it's convenient for computers to "sign-extend" the most significant bit of a number as though it represented an infinite number of 1's or 0's.
Two's-complement is just about the only signed-number representation that works well when dealing with types larger than a binary machine's natural word size, since when performing addition or subtraction, code can fetch the lowest chunk of each operand, compute the lowest chunk of the result, and store that, then load the next chunk of each operand, compute the next chunk of the result, and store that, etc. Thus, even a processor which requires all additions and subtractions to go through a single 8-bit register can handle 32-bit signed numbers reasonably efficiently (slower than with a 32-bit register, of course, but still workable).
当使用C标准所允许的任何其他有符号表示时,结果的每一位都可能受到操作数的任何位的影响,这就需要将整个值一次保存在寄存器中,或者在计算之后进行额外的步骤,至少在某些情况下,需要读取、修改和重写结果的每个块。