为什么~2等于-3?~操作符是如何工作的?
当前回答
简单地说,~就是找到对称值(到-0.5)。
~a和a应该与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)。
其他回答
我认为对于大多数人来说,困惑的部分来自于十进制数和有符号二进制数的区别,所以让我们先澄清一下:
对于人类十进制世界: 01表示1, -01表示-1, 对于计算机的二进制世界: 101是无符号的,表示5。 101的意思是(-4 + 1),如果是有符号的数字在x位置。 | x
所以2的翻转位= ~2 = ~(010)= 101 = -4 + 1 = -3 这种混淆是由于混淆了有符号的结果(101=-3)和没有符号的结果(101=5)
Tl;dr ~翻转比特。结果符号就改变了。~2是负数(0b..101)。要输出一个负数红宝石打印-,则2的~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)。= = true)。要输出一个负数的红宝石印-,则是二的内部补值。2的补位是通过翻转位,然后加1来计算的。0b的2的补。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像这样输出负数的原因是,它将存储的值视为绝对值的2的补。换句话说,存储的是0b..101。它是一个负数,因此它是x的2的补,为了找到x,它是2的补0b..101。它是2的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的2的补。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)来计算它们。bit_length == 4). But ~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"
正如其他人所提到的~只是翻转位(将1变为0,将0变为1),由于使用了2的补码,您就得到了您所看到的结果。
需要补充的一点是为什么使用2的补数,这是为了对负数的运算和对正数的运算是一样的。把-3看成是要加3才能得到0的数字,你会看到这个数字是1101,记住二进制加法就像小学(十进制)加法,只是你得到2时进1,而不是10。
1101 +
0011 // 3
=
10000
=
0000 // lose carry bit because integers have a constant number of bits.
因此1101是-3,翻转位就得到0010,也就是2。
int = 4; System.out.println (~); 结果是:-5
Java中任意整数的“~”表示1对no的补。 例如,我取~4,这意味着用二进制表示0100。 首先, 整数长度为4字节,i。e4 *8(8位1字节)=32。 在系统内存中,4表示为 0000 0000 0000 0000 0000 0000 0000 0100 现在~操作符将对上面的二进制no执行1的补
i.e 1111 1111 1111 1111 1111 1111 1111 1011->1's complement the most significant bit represents sign of the no(either - or +) if it is 1 then sign is '-' if it is 0 then sign is '+' as per this our result is a negative number, in java the negative numbers are stored in 2's complement form, the acquired result we have to convert into 2's complement( first perform 1's complement and just add 1 to 1's complement). all the one will become zeros,except most significant bit 1(which is our sign representation of the number,that means for remaining 31 bits 1111 1111 1111 1111 1111 1111 1111 1011 (acquired result of ~ operator) 1000 0000 0000 0000 0000 0000 0000 0100 (1's complement)
1(2的补数)
1000000 0000 0000 0000 0000 0000 0000 0101 现在结果是-5 查看视频<[java中的位运算符]https://youtu.be/w4pJ4cGWe9Y的链接
这个操作是补语,不是否定语。
考虑~0 = -1,然后从这里开始。
否定的算法是,“补,加”。
你知道吗?还有一种“一的补”,它的逆数是对称的,它有一个0和一个-0。