java 一元“~”运算符 - 这里到底发生了什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13535947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unary "~" operator - What exactly is happening here?
提问by Penelope The Duck
I recently did a Java course (1 week crash course), and we covered some binary mathematics.
我最近参加了 Java 课程(1 周速成课程),我们涵盖了一些二进制数学。
This unary ~ operator (tilde I think it's called?) was explained to us thus:
这个一元 ~ 运算符(波浪号我认为它被称为?)向我们解释如下:
It inverts the bit pattern turning every "0" into a "1" and every "1" into a "0". e.g. There are 8 bits to a byte. If you have the following byte: 00000000 the inverted value would change to become 11111111.
它反转位模式,将每个“0”变为“1”,将每个“1”变为“0”。例如,一个字节有 8 位。如果您有以下字节:00000000,反转值将变为 11111111。
The above explanation is clear and concise, and totally makes sense to me. Until, that is, I try to implement it.
上面的解释清晰简洁,对我来说完全有道理。直到,也就是说,我尝试实施它。
Given this:
鉴于这种:
byte x = 3;
byte y = 5;
System.out.println(~x);
System.out.println(~y);
The output is:
输出是:
-4
-6
I'm very confused about how this happens.
我很困惑这是怎么发生的。
If +3 in binary is 11, then the inversion of this would be 00, which clearly isn't -3.
如果二进制中的 +3 是 11,那么它的倒数就是 00,这显然不是 -3。
But as there are 8 bits in a byte, then shouldn't the binary representation of +3 be written as 00000011?
但是由于一个字节有 8 位,那么 +3 的二进制表示不应该写为 00000011 吗?
Which would invert to become 11111100. Converted back to decimal value this would be 252. If however you write the +3 as 011, then it does indeed convert to 100, which is +4, but then how do you know it's a negative number?
这将反转为 11111100。转换回十进制值这将是 252。但是,如果您将 +3 写为 011,那么它确实会转换为 100,即 +4,但是您怎么知道它是负数?
How about if you try 0011, which converts to 1100, which if you use the first bit as a sign, then it does indeed become -4.
如果你尝试 0011,它会转换为 1100,如果你使用第一位作为符号,那么它确实变成了 -4。
Ah - so at this point I thought I was getting somewhere.
啊 - 所以在这一点上我以为我到了某个地方。
But then I got to the second value of y = 5.
但后来我得到了 y = 5 的第二个值。
How do we write this? Using the same logic, +5 converts to binary 0101, which inverts to 1010.
我们怎么写这个?使用相同的逻辑,+5 转换为二进制 0101,后者又转换为 1010。
And it's around now that I'm horribly confused. This looks to represent either a signed value of -2, or an unsigned value of +10 decimal? Neither of which are the -6 I'm getting printed out.
现在我非常困惑。这看起来代表 -2 的有符号值,还是十进制 +10 的无符号值?这两个都不是我打印出来的 -6。
Again, if I increase the length up to the 8 digits of a byte, +5 is 00000101, which inverted becomes 11111010. And I really can't find a way to turn this into -6.
同样,如果我将长度增加到一个字节的 8 位数字,+5 是 00000101,它反转后变成 11111010。我真的找不到将它变成 -6 的方法。
Does anyone out there understand this, as I have no idea what is happening here and the more numbers I print out the more confused I become.
有没有人理解这一点,因为我不知道这里发生了什么,我打印的数字越多,我就越困惑。
Google doesn't seem to come up with anything much on this - maybe it doesn't like looking at little operator signs.. :-(
谷歌似乎并没有想出任何关于这个的东西 - 也许它不喜欢看小的运营商标志.. :-(
采纳答案by John Smithers
From wikipedia: In two's complement notation, a non-negative number is represented by its ordinary binary representation; in this case, the most significant bit is 0. The two's complement operation is the negation operation, so negative numbers are represented by the two's complement of the absolute value.
To get the two's complement of a binary number, the bits are inverted, or "flipped", by using the bitwise NOT operation; the value of 1 is then added to the resulting value, ignoring the overflow which occurs when taking the two's complement of 0. http://en.wikipedia.org/wiki/Two%27s_complement
来自维基百科:在二进制补码表示法中,非负数由其普通二进制表示法表示;在这种情况下,最高有效位为0。二进制补码运算是求反运算,因此负数用绝对值的二进制补码表示。
要获得二进制数的二进制补码,需要使用按位非运算反转或“翻转”位;然后将 1 的值添加到结果值中,忽略取 0 的二进制补码时发生的溢出。http://en.wikipedia.org/wiki/Two%27s_complement
So if you have 0101 which is +5 the inverse of that is 1010, which is -5.
因此,如果您有 0101,它是 +5,那么它的倒数是 1010,即 -5。
You don't really read the 010 as a 5 though, but when you see the 1 at the beginning, you know that to get the number you have to invert the rest of the digits again to get the positive number which you want to negate. If that makes sense.
虽然你并没有真正将 010 读为 5,但是当你看到开头的 1 时,你知道要得到这个数字,你必须再次反转其余的数字来得到你想要取反的正数. 如果这是有道理的。
It's a bit of an alien concept if you have not worked with it before. It's certainly not the way that decimal numbers work, but it is actually simple once you see what happening.
如果您以前没有使用过它,这有点陌生。这当然不是十进制数的工作方式,但一旦你看到发生了什么,它实际上很简单。
A value of 8 decimal is written as 01010, which negates to 10101. The first digit (1) means it's negative, and then you flip the rest back to get the numeric value: 1010.
8位十进制数写成01010,与10101取反。第一个数字(1)表示它是负数,然后你把剩下的翻转回来得到数值:1010。
One thing to remember is that Two's complement is not the same as ordinary old binary system counting. In normal binary the value of 10101 (which in Two's complement is -8 as above) is of course 21. I guess this is where the confusion comes - how do you tell the difference by looking at them? You must know which representation has been used in order to decide what the value of the number actually is. There is also One's complement which differs slightly.
要记住的一件事是,Two 的补码与普通的旧二进制系统计数不同。在正常的二进制中,10101 的值(在上面的二进制补码中是 -8)当然是 21。我想这就是混淆的地方 - 你如何通过查看它们来区分?您必须知道使用了哪种表示法才能确定数字的实际值。还有一个 One's 补码,略有不同。
A good tutorial on binary maths, including One's and Two's complement is given here. http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary
这里给出了一个关于二进制数学的很好的教程,包括一个和两个的补码。 http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary
回答by Rohit Jain
See this demonstration: -
请参阅此演示:-
3 -> 0011
~3 -> 1100 -> -4 (2's complement)
5 -> 0101
~5 -> 1010 -> -6 (2's complement)
Since signed integers are stored as 2's complement, taking 2's complement
of 1100
gives you 4
. Now since 1100
is a negative number. So, the result is -4
. Same is the case with 1010
.
由于有符号整数存储为 2 的补码,因此采用2's complement
of1100
为您提供4
. 现在因为1100
是负数。所以,结果是-4
。的情况也是如此1010
。
1100
0011 - 1's complement
0100 - 2's complement - value = 4 (take negative)
回答by Jonathan Dursi
Signed integers are almost universally stored using twos complement. This means inverting the bits (taking the one's complement) and adding one. This way you don't have two representations of integer zero (+0 and -0), and certain signed operations become easier to implement in hardware.
有符号整数几乎普遍使用二进制补码存储。这意味着反转位(取其补码)并加一。这样你就没有整数零的两种表示(+0 和 -0),并且某些有符号运算在硬件中变得更容易实现。
回答by LtWorf
Java uses signed numbers in Two's complement. Your reasoning would be correct in C or other languages when using types as "unsigned int" or "unsigned char".
Java 在二进制补码中使用有符号数。当将类型用作“unsigned int”或“unsigned char”时,您的推理在 C 或其他语言中是正确的。