Answers:
请记住,负数存储为正数的二进制补码。例如,这是-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的二进制补码表示形式。
正如其他人提到的那样,~
只是翻转位(将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
这是两个。
我知道这个问题的答案已经发布很久了,但是我想分享我的答案。
为了找到一个数字的补码,首先找到它的二进制等价物。在此,十进制数以二进制形式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 0011
是3
。并且,由于符号位是如上所述的一位,因此得出的答案为-3
。
提示:如果您仔细阅读此过程,那么您会发现一个补码运算符的结果实际上是数字(操作数-应用此运算符的对象)加上一个带负号的数字。您也可以尝试使用其他号码。
add, flip, add
。0010
-> 0011
-> 1100
->1101
0010
1101
0010
NOT 0 = 1
和NOT 1 = 0
。在四位系统中,NOT 0011
(3)= 1100
(12个无符号,-4个有符号)。据我了解,二进制补码定义为(NOT n) + 1
,用于查找数字的负数对数,而与位数无关。因此,2c(5) = -5
。瞧,现在这很合理了。只要您将此操作称为“什么”:按位“不”。
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的补码)
1000 0000 0000 0000 0000 0000 0000 0101现在的结果是-5签出该视频链接<[java中的位运算符] https://youtu.be/w4pJ4cGWe9Y
只是...
作为任何数字的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。
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"
~
翻转内部值的位。2
是0b010
。~2
是0b..101
。两个点(..
)代表无数个1
。由于结果的最高有效位(MSB)为,因此1
结果为负数((~2).negative? == true
)。要输出负数,将ruby
打印-
,然后是内部值的二进制补码。二进制补码是通过翻转位然后加来计算的1
。的补码0b..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_length
(0x0f.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"
首先,我们必须将给定的数字拆分为二进制数字,然后通过在最后一个二进制数字加法来反转它。执行此操作后,我们必须给与前一个数字相反的符号,即我们找到了〜2 = -3 :将2s的二进制形式从00000010更改为11111101,这是一个补码,然后将00000010 + 1 = 00000011增强为3的二进制形式,并带有-sign Ie,-3
按位运算符是一元运算符,根据我的经验和知识,该运算符适用于符号和幅度方法。
例如〜2将导致-3。
这是因为按位运算符将首先以符号和大小表示数字,即0000 0010(8位运算符),其中MSB是符号位。
然后,它将取负数2,即-2。
-2的符号和大小表示为1000 0010(8位运算符)。
后来,它在LSB(1000 0010 +1)上加了1,从而得到1000 0011。
这是-3。
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
以上所有条件同时适用。