按位补码运算符(~tilde)如何工作?

时间:2009-04-26 18:29:47

标签: operators bitwise-operators complement

为什么~2等于-3? ~运算符如何工作?

17 个答案:

答案 0 :(得分:256)

请记住,负数存储为正对应的二进制。作为一个例子,这里是二进制补码中-2的表示:( 8位)

1111 1110

你得到这个的方法是取一个数字的二进制表示,取其补码(反转所有位)并加一个。两个开始为0000 0010,通过反转我们得到的位1111 1101.添加一个得到我们上面的结果。第一位是符号位,表示负数。

那么让我们来看看我们如何得到~2 = -3:

这是两个:

0000 0010

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

1111 1101

嗯,在二补码中-3是什么样的?从正3:0000 0011开始,将所有位翻转到1111 1100,并添加一个变为负值(-3),1111 1101.

因此,如果您只是将2中的位反转,则得到-3的二进制补码表示。

补码运算符(〜)JUST FLIPS BITS。由机器来解释这些位。

答案 1 :(得分:35)

~翻转值中的位。

为什么~2 -3与数字按位表示的方式有关。数字表示为two's complement

所以,2是二进制值

00000010

并且~2翻转这些位,现在值为:

11111101

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

答案 2 :(得分:15)

正如其他人提到的那样~只是翻转位(将一个变为零,零变为一个),并且由于使用two's complement,您将得到您所看到的结果。

要添加的一件事是为什么使用了两个补码,这样负数的运算与正数的运算相同。将-3视为要添加3以便获得零的数字,您会看到此数字为1101,请记住二进制加法就像小学一样(十进制)只有当你到达两个而不是10时才携带一个。

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

因此1101-3,将您获得的位0010翻转为两位。

答案 3 :(得分:8)

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

考虑〜0 = -1,并从那里开始工作。

否定算法是“补充,增量”。

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

答案 4 :(得分:4)

我知道这个问题的答案是在很久以前发布的,但我想分享我的答案。

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

0000 0010 → 1111 1101

这是十进制数2的一个补码。并且由于第一位,即二进制数中的符号位为1,这意味着该数字的符号为负数存储。 (这里,所提到的数字是 2但是2的补码。)

现在,因为数字被存储为2的补码(取一个数的加1),所以要将这个二进制数1111 1101显示为十进制,首先我们需要找到它的2的补码,这将是:

1111 1101 → 0000 0010 + 1 → 0000 0011

这是2的补充。二进制数0000 0011的十进制表示为3。并且,由于符号位是如上所述的一个,因此得到的答案是-3

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

答案 5 :(得分:4)

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

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

执行1补码

,即1111 1111 1111 1111 1111 1111 1111 1011-> 1' s补 最重要的位表示否的符号(或 - 或+) 如果它是1那么签名是' - ' 如果它是0那么签名是' +' 据此,我们的结果是负数, 在java中,负数以2的补码形式存储, 我们必须将获得的结果转换为2的补码(首先执行1&#39的补码,然后加1到1的补码)。 所有的一个都将变为零,除了最重要的位1(这是我们的数字的符号表示,这意味着剩余的31位) 1111 1111 1111 1111 1111 1111 1111 1011(〜运算符的获得结果) 1000 0000 0000 0000 0000 0000 0000 0100(1' s补充)

1(2' s补充)

1000 0000 0000 0000 0000 0000 0000 0101 现在结果是-5 看看这个视频链接< [java中的比特运算符] https://youtu.be/w4pJ4cGWe9Y

答案 6 :(得分:2)

简单来说,~就是求对称值(到-0.5)。

~aa 应该在 0 和 -1 的中间对称于镜像。

-5,-4,-3,-2,-1 | 0、1、2、3、4

~0 == -1
~1 == -2
~2 == -3
~3 == -4

这是因为计算机如何表示负值。

比如说,如果正值使用1来计数,负值使用0

1111 1111 == -1

1111 1110 == -2; // add one more '0' to '1111 1111'

1111 1101 == -3; // add one more '0' to '1111 1110'

最后,~i == -(i+1)

答案 7 :(得分: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 

现在点是Minus来的地方。我的观点是假设我们有32位寄存器,这意味着操作中涉及2 ^ 31 -1位,并且在早期计算(补码)中改变一位,存储为通常为1的符号位。我们得到的结果为~10 = -11。

〜(-11)= 10;

如果是printf(“%d”,~0),则上述情况属实;我们得到结果:-1;

但是printf(“%u”,~0)比32位机器上的结果:4294967295。

答案 8 :(得分:1)

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

按照以下方法工作

首先,它将给定的十进制数转换为相应的二进制 在2的情况下,它首先将2转换为0000 0010(到8位二进制数)。

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

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

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

答案 9 :(得分:1)

我认为对于大多数人来说,混淆部分来自十进制数和带符号二进制数之间的差异,所以我们先说清楚它:

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

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

答案 10 :(得分: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,请先打印-,然后输出内部值的2的补码。二进制补码的计算方法是翻转位,然后加10b..101的二进制补码为3。因此:

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..f0f的二进制补码为0xf1。所以:

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"

答案 11 :(得分:1)

此处,二进制(8位)中的2为00000010,其1的补码为11111101, 从1的补码中减去1,我们得到11111101-1 = 11111100, 这里的符号是-因为第8个字符(从R到L)是1 找到1的补码。即00000011 = 3 而且符号为负,这就是我们在这里得到-3的原因。

答案 12 :(得分:0)

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

例如~2会导致-3。

这是因为逐位运算符首先表示符号和幅度的数字,即0000 0010(8位运算符),其中MSB是符号位。

然后它将取2的负数-2。

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

稍后它会向LSB(1000 0010 + 1)添加1,这会给你1000 0011.

这是-3。

答案 13 :(得分:0)

Javascript代字号(〜)将给定值强制转换为补码 - 所有位都反转。 所有代言人都这样做。它没有表明自己的观点。 既不添加也不减去任何数量。

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

在使用JavaScript等高级语言的标准桌面处理器上,BASE10签名算法是最常见的,但请记住,它并不是唯一的类型。 CPU级别的位可以根据许多因素进行解释。在&#39;代码&#39; level,在这种情况下是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 

所有这些都是同时存在的。

答案 14 :(得分:0)

首先,我们必须将给定的数字拆分成二进制数字,然后通过添加最后一位二进制数字来反转它。执行完毕后,我们必须给上一个数字给出相反的符号,我们发现它是完全的 〜2 = -3 说明: 2s二进制形式是00000010更改为11111101这是一个补码,然后完成00000010 + 1 = 00000011这是二进制形式的三个并且带有-sign I.e,-3

答案 15 :(得分:0)

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

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

x =〜2

-((2 + 1)

-3

答案 16 :(得分:0)

很简单:

Before starting please remember that 
 1  Positive numbers are represented directly into the memory.
 2. Whereas, negative numbers are stored in the form of 2's compliment.
 3. If MSB(Most Significant bit) is 1 then the number is negative otherwise number is 
    positive.

你发现了~2:

Step:1 Represent 2 in a binary format 
       We will get, 0000 0010
Step:2 Now we have to find ~2(means 1's compliment of 2)
                  1's compliment       
       0000 0010 =================> 1111 1101 

       So, ~2 === 1111 1101, Here MSB(Most significant Bit) is 1(means negative value). So, 
       In memory it will be represented as 2's compliment(To find 2's compliment first we 
       have to find 1's compliment and then add 1 to it.)
Step3:  Finding 2's compliment of ~2 i.e 1111 1101

                   1's compliment                   Adding 1 to it
        1111 1101 =====================> 0000 0010 =================> 0000 0010
                                                                      +       1
                                                                      ---------
                                                                      0000 0011 
        So, 2's compliment of 1111 1101, is 0000 0011 

Step4:  Converting back to decimal format.
                   binary format
        0000 0011 ==============> 3
        
       In step2: we have seen that the number is negative number so the final answer would  
       be -3
                                    
                                So, ~2 === -3