我最近做了Java课程(1周速成课程),我们介绍了一些二进制数学.
这个一元〜运算符(代字号,我认为它被称为?)向我们解释了:
它将位模式反转,每"0"变为"1",每"1"变为"0".例如,一个字节有8位.如果您有以下字节:00000000,则反转值将更改为11111111.
以上解释清晰简洁,对我来说完全有道理.直到,也就是说,我试图实现它.
鉴于这种:
byte x = 3;
byte y = 5;
System.out.println(~x);
System.out.println(~y);
Run Code Online (Sandbox Code Playgroud)
输出是:
-4
-6
Run Code Online (Sandbox Code Playgroud)
我对这是怎么回事感到很困惑.
如果二进制中的+3是11,那么这个的反转将是00,这显然不是-3.
但由于一个字节中有8位,那么+3的二进制表示不应写为00000011吗?
哪个会反转成11111100.转换回十进制值这将是252.如果你将+3写为011,那么它确实转换为100,即+4,但那么你怎么知道它是负数?
如果你尝试0011,转换为1100,如果你使用第一位作为符号,那么它确实变为-4.
啊 - 所以在这一点上,我以为我到了某个地方.
但后来我得到了y = 5的第二个值.
我们怎么写这个?使用相同的逻辑,+ 5转换为二进制0101,其反转为1010.
而现在,我非常困惑.这看起来代表有符号值-2,或无符号值+10十进制?这些都不是-6我打印出来的.
再次,如果我将长度增加到一个字节的8位数,+ 5是00000101,其反转变为11111010.而且我真的找不到将其转换为-6的方法.
有没有人明白这一点,因为我不知道这里发生了什么,我打印的数字越多,我就越困惑.
谷歌似乎没有提出任何关于这一点 - 也许它不喜欢看小运营商的迹象.. :-(
看这个演示: -
3 -> 0011
~3 -> 1100 -> -4 (2's complement)
5 -> 0101
~5 -> 1010 -> -6 (2's complement)
Run Code Online (Sandbox Code Playgroud)
由于有符号整数存储为2的补码,因此2's complement可以1100得到4.现在既然1100是负数.所以,结果是-4.情况也是如此1010.
1100
0011 - 1's complement
0100 - 2's complement - value = 4 (take negative)
Run Code Online (Sandbox Code Playgroud)
来自维基百科:在补码表示法中,非负数由其普通的二进制表示形式表示;在这种情况下,最高有效位为 0。 二进制补码运算是求反运算,因此负数由绝对值的二进制补码表示。
为了获得二进制数的补码,通过使用按位 NOT 运算将位反转或“翻转”;然后将 1 的值添加到结果值中,忽略取 0 的二进制补码时发生的溢出。http://en.wikipedia.org/wiki/Two%27s_complement
因此,如果您有 0101(+5),则其倒数为 1010(-5)。
虽然你并没有真正将 010 读作 5,但是当你看到开头的 1 时,你知道要得到这个数字,你必须再次反转其余的数字以获得你想要求反的正数。如果这是有道理的话。
如果您以前没有使用过它,那么这有点陌生。这当然不是十进制数的工作方式,但一旦你看到发生了什么,它实际上很简单。
十进制 8 的值写为 01010,它的负数是 10101。第一个数字 (1) 表示它是负数,然后将其余数字翻转回来得到数值:1010。
要记住的一件事是,二进制补码与普通的旧二进制系统计数不同。在普通二进制中,10101 的值(如上所述,在二进制补码中为 -8)当然是 21。我想这就是令人困惑的地方 - 你如何通过查看它们来区分它们?您必须知道使用了哪种表示形式才能确定数字的实际值。还有一个略有不同的补码。
这里给出了关于二进制数学的一个很好的教程,包括一个和两个的补码。 http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary
| 归档时间: |
|
| 查看次数: |
11713 次 |
| 最近记录: |