0

我刚刚开始学习按位运算符(尽管我正在努力寻找任何绝对的初学者资源)。我了解二进制的工作原理以及如何阅读它,但我不明白以下内容。

如果您将数字 37 取为二进制: 00100101并对其应用 ~(NOT) 运算符,则位会翻转到 11011010 在我正在阅读的教程中,它说您必须在其中添加一个作为一种标志来表示它是否定的. 于是就变成了11011011。我不明白为什么这个新数字不只是读作 219。

在相关的说明中,是否有人深入解释了我可以用来真正深入了解所有这些并最终理解这一切的所有资源?

4

2 回答 2

5

按位NOT也称为1s 补码

您可以通过加 1 将 1s 补码转换为2s 补码

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 补码中不可用的附加负值(在 8 位整数的情况下为 -128)。

于 2013-08-30T09:39:53.420 回答
2

“我不明白为什么这个新数字不只是读为 219”的答案必须是“因为已知位的解释是有符号的,并且使用 2s 补码”。

位只是位,您必须指定解释才能应用规则,例如您引用的规则。

如果该数字被认为是无符号整数,则应将其转换为十进制的 219。如果将其视为有符号整数,则应将其转换为 -37。

您可以通过运行这个小 C 程序轻松地尝试一下:

#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;
}

它打印“-37 还是 219?” 因为在这两种情况下对位的解释是不同的。这& 255部分只是为了去掉较高值的位,否则它们会让人很困惑(C 的int整数类型大于 8 位)。

于 2013-08-30T09:55:43.537 回答