按位补码运算符(〜波浪号)如何工作?


Answers:


279

请记住,负数存储为正数的二进制补码。例如,这是-2的补码表示形式:(8位)

1111 1110

您可以通过采用数字的二进制表示形式,采用补码(将所有位取反)并加一个的方式来实现。两个以0000 0010开头,通过将位取反得到11111101。加一个得到上面的结果。第一位是符号位,表示负数。

因此,让我们看一下如何得到〜2 = -3:

再来两个:

0000 0010

只需翻转所有位,我们就会得到:

1111 1101

那么,-2的补码是什么样子的-3呢?从正数3开始:0000 0011,将所有位翻转到1111 1100,然后加一成为负值(-3)1111 1101。

因此,如果仅将2中的位取反,则得到-3的二进制补码表示形式。

补码运算符(〜)仅是位。由机器来解释这些位。


43
另一件事也许要提的是,翻盖被称为1的补码,加入1之前
克里斯小号

3
它可能会帮助那些不知道一个人的补语和两个人的补语的人。在这里阅读有关它们的信息。 en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement

1
这不是按位NOT运算符吗?
Braden Best

3
机器如何知道它得到的是两个补数负数而不是一个较高的正数?是否由于相应语言的类型系统指示该类型是带符号的int而不是无符号的?
GL2014 '16

@ GL2014我认为您在那里回答了自己的问题。在我的理解中,这就是机器最初是如何工作的。
geekidharsh

40

~ 翻转值中的位。

为什么~2-3有编号的方式逐位代表做。数字表示为二进制补码

所以2是二进制值

00000010

〜2翻转位,所以现在的值是:

11111101

其中,-3的二进制表示形式。


2
11111101 ==十进制253对-3吗?
AKS

10
取决于它代表有符号还是无符号整数。
driis '16

18

正如其他人提到的那样,~只是翻转位(将1更改为零,将0更改为1),并且由于二进制补码使用了,因此您可以看到结果。

要添加的一件事是为什么要使用二进制补码,这是为了使负数运算与正数运算相同。想想-3哪个数量3应该按顺序相加得到零,你会看到,这个数字1101,请记住,二进制加法就像小学(十进制)除了只有你携带一个,当你两个,而不是10 。

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

因此1101-3,翻转你的位0010这是两个。


8

此操作是补充,而不是否定。

考虑〜0 = -1,然后从那里开始。

求反的算法是“补数,增量”。

你知道吗?还有一个“补码”,其中的逆数对称的,并且都具有0和-0。


6

我知道这个问题的答案已经发布很久了,但是我想分享我的答案。

为了找到一个数字的补码,首先找到它的二进制等价物。在此,十进制数以二进制形式2表示0000 0010。现在,通过将其二进制表示的所有数字取反(将全1翻转为0,将全0翻转为1)来获得其补码,这将导致:

0000 0010 → 1111 1101

这是十进制数字2的补码。并且由于第一位(即,二进制数中的符号位为1),这意味着符号对其存储的数字为。(此处所指的号码不是 2,而是2的补数)。

现在,由于数字存储为2的补数(取一个数字的一​​个补数加一个),因此要将此二进制数显示1111 1101为十进制,首先我们需要找到其2的补码,即:

1111 1101 → 0000 0010 + 1 → 0000 0011

这是2的补码。二进制数的十进制表示形式0000 00113。并且,由于符号位是如上所述的一位,因此得出的答案为-3

提示:如果您仔细阅读此过程,那么您会发现一个补码运算符的结果实际上是数字(操作数-应用此运算符的对象)加上一个带负号的数字。您也可以尝试使用其他号码。


为什么加两次?我看到了add, flip, add0010-> 0011-> 1100->1101
Braden Best

1
它是翻转,翻转,添加。第一个翻转为1的补码。而且,由于它以2的补码形式存储在系统中,因此当您需要显示数字时,它将显示所存储数字的2的补码(即第二次翻转和加法)。
Himanshu Aggarwal,2015年

但是flip(flip(2))不会只是2吗?0010 1101 0010
Braden Best

是的,它只会是2。但是由于将这些位存储在内存中时,最高有效位为1,这将使该数变为负数,如上面的答案所述。
Himanshu Aggarwal

1
根据您的描述以及我研究的所有内容,这不是二进制补码,而是“常规”补码或按位取反。在逻辑上,NOT 0 = 1NOT 1 = 0。在四位系统中,NOT 0011(3)= 1100(12个无符号,-4个有符号)。据我了解,二进制补码定义为(NOT n) + 1,用于查找数字的负数对数,而与位数无关。因此,2c(5) = -5。瞧,现在这很合理了。只要您将此操作称为“什么”:按位“不”。
Braden Best

4

int a = 4; System.out.println(〜a); 结果将是:-5

Java中任何整数的“〜”表示no的1的补码。例如我取〜4,这意味着二进制表示为0100。首先,整数的长度为四个字节,即4 * 8(1个字节为8位)= 32。因此在系统存储器4中表示为0000 0000 0000 0000 0000 0000 0000 0100现在〜运算符将对上述二进制数执行1的补码no

即1111 1111 1111 1111 1111 1111 1111 1011-> 1的补码,最高有效位代表no的符号(-或+),如果为1,则符号为'-';如果为0,则符号为'+'我们的结果是一个负数,在Java中,负数以2的补码形式存储,获取的结果必须转换为2的补码(首先执行1的补码,然后将1加1的补码)。除最高有效位1(这是我们的数字符号表示)外,所有1都将变为零。这意味着剩余的31位1111 1111 1111 1111 1111 1111 1111 1011(〜运算符的获取结果)1000 0000 0000 0000 0000 0000 0000 0100(1的补码)

1(2的补码)

1000 0000 0000 0000 0000 0000 0000 0101现在的结果是-5签出该视频链接<[java中的位运算符] https://youtu.be/w4pJ4cGWe9Y


2

只是...

作为任何数字的2的补码,我们可以通过将所有1都反转为0(反之亦然)来计算,而不是加1。

在这里N =〜N总是产生结果-(N + 1)。因为系统以2的补码形式存储数据,这意味着它像这样存储〜N。

  ~N = -(~(~N)+1) =-(N+1). 

例如::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

现在的关键是减号的来源。我的观点是,假设我们有32位寄存器,这意味着2 ^ 31 -1位参与操作,而剩下的一位则在较早的计算(补码)中以通常为1的符号位存储。我们得到的结果为〜10 = -11。

〜(-11)= 10;

如果printf(“%d”,〜0);则上述情况成立。我们得到结果:-1;

但是printf(“%u”,〜0)的结果是:在32位计算机上为4294967295。


1

按位补数运算符(〜)是一符。

它按照以下方法工作

首先,它将给定的十进制数转换为其对应的二进制数 值;如果为2,则首先将2转换为0000 0010(转换为8位二进制数)。

然后将数字中的所有1转换为0,并将所有零转换为1;然后数字将变为1111 1101。

那是-3的2的补码表示。

为了使用补码找到无符号值,即简单地将1111 1101转换为十进制(= 4294967293),我们可以在打印过程中简单地使用%u。


1

我认为对于大多数人来说,混淆部分来自十进制数和带符号的二进制数之间的差异,因此让我们首先澄清一下:

对于人类十进制世界:01表示1,-01表示-1,对于计算机二进制世界:101表示5(如果未签名)。101表示(-4 + 1)如果在已签名数字位于x位置时已签名。| X

所以2的翻转位=〜2 =〜(010)= 101 = -4 + 1 = -3混淆来自混淆带符号的结果(101 = -3)和未合并的结果(101 = 5)


1

tl; dr ~翻转位。结果,标志改变了。~2是负数(0b..101)。要输出负数ruby打印-,然后二进制补码~2-(~~2 + 1) == -(2 + 1) == 3。正数按原样输出。

有一个内部值及其字符串表示形式。对于正整数,它们基本上重合:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

后者等效于:

irb(main):003:0> 2.to_s
"2"

~翻转内部值的位。20b010~20b..101。两个点(..)代表无数个1。由于结果的最高有效位(MSB)为,因此1结果为负数((~2).negative? == true)。要输出负数,将ruby打印-,然后是内部值的二进制补码。二进制补码是通过翻转位然后加来计算的1。的补码0b..1013。因此:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

总结起来,它会翻转位,从而改变符号。要输出负数,它会打印-,然后~~2 + 1~~2 == 2)。

之所以这样ruby输出负数,是因为它将存储的值视为绝对值的二进制补码。换句话说,存储的是0b..101。这是一个负数,因此是某个值的二进制补码x。要找到x,它做的补码0b..101。这是的二进制补码x。哪个是x(例如~(~2 + 1) + 1 == 2)。

如果您申请~一个负数,它只会翻转位(尽管如此会改变符号):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

更令人困惑的是~0xffffff00 != 0xff(或MSB等于的任何其他值1)。让我们简化一下:~0xf0 != 0x0f。那是因为它被视为0xf0正数。这实际上是有道理的。因此,~0xf0 == 0x..f0f。结果为负数。的补码0x..f0f0xf1。所以:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

如果您不打算对结果应用按位运算符,则可以考虑将其~视为-x - 1运算符:

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

但这可以说没有多大用处。

一个示例假设您得到一个8位(为简单起见)网络掩码,并且您要计算的数量0。您可以通过翻转位并调用bit_length0x0f.bit_length == 4)来计算它们。但是~0xf0 == 0x..f0f,因此我们必须删除不需要的位:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

或者,您可以使用XOR运算符(^):

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"

0

首先,我们必须将给定的数字拆分为二进制数字,然后通过在最后一个二进制数字加法来反转它。执行此操作后,我们必须给与前一个数字相反的符号,即我们找到了〜2 = -3 :将2s的二进制形式从00000010更改为11111101,这是一个补码,然后将00000010 + 1 = 00000011增强为3的二进制形式,并带有-sign Ie,-3


0

按位运算符是一元运算符,根据我的经验和知识,该运算符适用于符号和幅度方法。

例如〜2将导致-3。

这是因为按位运算符将首先以符号和大小表示数字,即0000 0010(8位运算符),其中MSB是符号位。

然后,它将取负数2,即-2。

-2的符号和大小表示为1000 0010(8位运算符)。

后来,它在LSB(1000 0010 +1)上加了1,从而得到1000 0011。

这是-3。


0

Javascript波浪号(〜)将给定值强制转换为补码-所有位都被反转。 这就是波浪号所做的一切。它没有迹象表明。它既不增加也不减少任何数量。

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

在使用高级语言(例如JavaScript)的标准台式机处理器上,BASE10签名算术是最常见的方法,但请记住,它不是唯一的一种。CPU级别的位会根据多种因素进行解释。在“代码”级别,在这种情况下为JavaScript,根据定义,它们将被解释为32位带符号整数(让我们的假期浮出水面)。将其视为量子,这32位一次代表许多可能的值。这完全取决于您查看它们的转换镜头。

JavaScript Tilde operation (1's complement)

BASE2 lens
~0001 -> 1110  - end result of ~ bitwise operation

BASE10 Signed lens (typical JS implementation)
~1  -> -2 

BASE10 Unsigned lens 
~1  -> 14 

以上所有条件同时适用。


0

基本上,行动是一种补充,而不是一种否定。

在这里x =〜x总是产生-(x + 1)的结果。

x =〜2

-(2 + 1)

-3

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.