我无法理解以下内容:
在java中,
long l = 130L;
byte b = (byte)l;
如果我打印 b 的值,为什么会得到 -126?long l 的位表示是什么?
一个字节是一个 8 位的序列,这使得 2^8 例 = 256。其中一半表示负数,即 -128 到 -1。然后是0,大约一半,1到127代表正数。
130 因为 Int 看起来像 128 + 2 这是:
0000:0000 1000:0000 (128)
0000:0000 0000:0010 (2)
0000:0000 1000:0010 (130)
但是,字节只有 8 位数字,并且分配只采用原样的位,但仅采用最后一位:
1000:0010
第一位表示,它是一个负数。现在你需要添加多少才能达到零?让我们逐步进行:
1000:0010 x +
0000:0001 1 =
----------------
1000:0011 (x+1)
1000:0011 (x+1) +
0000:0001 1 =
----------------
1000:0100 (x+2)
让我们迈出更大的步伐。只需在我们有零的地方加 1,但首先我们回到 x:
1000:0010 x +
0111:1101 y =
--------------
1111:1111
现在出现了转折点:我们再加 1,得到 0(加上溢出)
1111:1111 (x + y) +
0000:0001 1
---------
0000:0000 0
如果 (x+y) + 1 = 0,则 x+y = -1。有趣的是,负 1 不仅与设置了“负标志”(“1000:0001”) 的 1 (0000:0001) 相同,而且看起来完全不同。但是,第一个位置总是告诉你符号:1 总是表示负数。
但是我们之前添加了什么?
0111:1101 y = ?
它在第一个位置没有 1,所以它是一个正值。我们知道如何解构它吗?
..f:8421 Position of value (1, 2, 4, 8, 16=f, 32, 64 in opposite direction)
0111:1101 y = ?
..f 84 1 = 1+4+8+16+32+64= 125
现在很清楚了:x+125 = -1 => x = -126
您可以想象将这些值组织成一个圆圈,顶部是 0(正午),正值排列在从 0 到 5(但到 127)的时钟上,底部是转折点(127 + 1 => -128 [原文如此!]。)现在您可以顺时针继续,将 1 导致 -127、-126、-125、... -3、-2、-1(在 11 点钟方向),最后0 再次在顶部。
对于更大的数字(小、整数、长),需要更大的时钟,零总是在顶部,最大值和最小值总是在底部。但即使是一个字节也太大了,无法制作图片,所以我制作了一个半字节,一个半字节:
您可以轻松填补图片中的漏洞,这很简单!
顺便说一句:整件事不叫cast。铸造只在对象之间使用。如果你有一些东西,它实际上是一个子类型:
Object o = new String ("casting or not?");
这只是一个赋值,因为字符串(总是)是一个对象。不涉及铸造。
String s = (String) o;
这是一个铸件。到更具体的类型。并非每个对象都是字符串。与整数提升有一个小的关系,因为每个字节都可以无损地转换为 long,但不是每个 long 都可以转换为字节。但是,即使是 Object 类型的 Byte 和 Long,也不是相互继承的。
你只是没有收到警告,因为
byte s = (byte) 42;
long o = s; // no problem, no warning
byte b = (byte) o; // written like casting
字节是用 Java 签名的 - 所以值的范围是 -128 到 127 (含)。
130 作为长的位模式,当简单地截断为 8 位时,是 -126 作为一个字节的位模式。
再举一个例子:
int x = 255;
byte b = (byte) x; // b is now -1
你的意思是byte b = (byte)l
?
Java 的类型是有符号的,因此字节允许介于 -128 和 +127 之间的数字。
初学者理解:1字节=8位范围(从2的补数系统派生)=[-2^(n-1) to 2^(n-1)-1],其中n为否。位数 所以范围是 -128 到 127
每当 value 增加超过可能的最高 +ve 值时,流程就会转到可能的最低 -ve 值。
因此,在值达到 127 后,流量从 -128 继续到 -127 到 -126 以覆盖 130 的总空间,因此 o/p 为 -126