Binary 按位运算符,为什么对已应用NOT运算符的二进制数加1会使其为负数而不是另一个数?
我刚刚开始学习位运算符(尽管我很难找到任何绝对的初学者资源)。我理解二进制文件的工作原理和读取方法,但我不理解以下内容 如果您使用二进制数字37:Binary 按位运算符,为什么对已应用NOT运算符的二进制数加1会使其为负数而不是另一个数?,binary,bit-manipulation,Binary,Bit Manipulation,我刚刚开始学习位运算符(尽管我很难找到任何绝对的初学者资源)。我理解二进制文件的工作原理和读取方法,但我不理解以下内容 如果您使用二进制数字37: 00100101并对其应用~(NOT)运算符,位被翻转到 11010 在我正在阅读的教程中,它说你必须添加一个1作为一种标志,以表示它是负的。因此它变成了11011011。我不明白为什么这个新数字不被读为219 在一个相关的注释中,是否有人有任何深度,解释我可以使用的所有资源,以真正让我的头脑进入这一切,并最终理解这一切 A也称为A 您可以通过添加1
00100101
并对其应用~(NOT)运算符,位被翻转到
11010
在我正在阅读的教程中,它说你必须添加一个1作为一种标志,以表示它是负的。因此它变成了11011011
。我不明白为什么这个新数字不被读为219
在一个相关的注释中,是否有人有任何深度,解释我可以使用的所有资源,以真正让我的头脑进入这一切,并最终理解这一切 A也称为A
您可以通过添加1将1s补码转换为
1s补码和2s补码都是表示负数的不同方式,但现在2s补码几乎被普遍使用
所以,要对2s补码形式的数字求反,只需应用按位NOT并加1,即
-x == ~x + 1
相反,要将2s补码数转换为1s补码,可以将其取反并减去1:
~x == -x - 1
请注意,正数在1s补码和2s补码表示中具有相同的表示形式-只有负数存在差异。例如,对于8位整数:
Decimal 1s complement 2s complement
0 00000000 00000000
-0 11111111 n/a
1 00000001 00000001
-1 11111110 11111111
2 00000010 00000010
-2 11111101 11111110
127 01111111 01111111
-127 10000000 10000001
-128 n/a 10000000
请注意,1s补码有两种十进制0的表示形式:+0和-0,而2s补码有唯一的零表示形式。2s补码还可以表示1s补码中不可用的附加负值(-128,在8位整数的情况下)。对于“我不明白为什么这个新数字不被理解为219”的答案必须是“因为已知位的解释是有符号的,并且使用2s补码”
位只是位,您必须指定一个解释才能应用规则,例如您正在引用的规则
如果该数字被视为无符号整数,则应将其转换为十进制的219。如果将其视为有符号整数,则应将其转换为-37
您可以通过运行以下命令轻松尝试此操作:
#包括
内部主(空)
{
常数int x=37;
常数y=~x+1;
printf(“%d或%u?\n”,y,y&255);
返回0;
}
它打印“-37或219”,因为在这两种情况下,位的解释不同。
&255
部分只是为了去掉较高值的位,因为它们会使它变得非常混乱(C的int
整数类型大于8位)。a-b
相当于a+~b+1
,因此0-x
相当于~x+1
。或者,a-b
也相当于~(~a+b)
,因此0-x
相当于~(x-1)
。另外,考虑一下:如果你将<代码> ~x添加到<代码> x>代码>,你会得到“所有的”,所以如果你再增加一个,你就会得到零。加上两个数字,得到零意味着它们彼此都是负数。这是否意味着最右边的二进制数字是一个表示负数的标志,而右边的第二个数字代表数字1?谢谢你,保罗。在我所做的几个小时的研究中,我已经看到了很多关于1和2的补充,所以我一定会看一看。
#include <stdio.h>
int main(void)
{
const int x = 37;
const int y = ~x + 1;
printf("%d or %u?\n", y, y & 255);
return 0;
}