我无法理解以下内容:在java中,
long l = 130L; byte b = (byte)l;
如果我打印B的值,为什么会得到-126?long l的位表示是什么?
jyztefdp1#
一个字节是一个8位的序列,这使得2^8个case = 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)
然而,Byte只有8位,赋值只取它们原来的位,但只取最后一位:
1000:0010
第一位表示,它是一个负数。现在你需要加多少才能得到零?让我们逐步进行:
1000:0010 x + 0000:0001 1 = ---------------- 1000:0011 (x+1) 1000:0011 (x+1) + 0000:0001 1 = ---------------- 1000:0100 (x+2)
让我们做更大的步骤。只要在我们有0的地方加上1,但首先我们回到x:
1000:0010 x + 0111:1101 y = -------------- 1111:1111
现在出现了转折点:我们再加1,得到零(加上溢出)
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 [sic!].)现在你可以顺时针继续,加上1会导致-127,-126,-125,... -3,-2,-1(在11点钟方向),最后又是0。对于更大的数字(small,int,long),采用更大的时钟,0总是在顶部,最大值和最小值总是在底部。但是即使是一个字节也太大了,无法制作图片,所以我制作了一个半字节的时钟:
你可以很容易地填补图片中的漏洞,这是微不足道的!顺便说一句:整个过程并不叫转换。转换只在对象之间使用。如果你有一些东西,真实的上是一个子类型:
Object o = new String ("casting or not?");
这仅仅是一个赋值,因为字符串(总是)是一个对象。不涉及转换。
String s = (String) o;
这是一个转换。转换到更具体的类型。不是每个对象都是String。与整数提升有一点关系,因为每个字节都可以无损地转换为long,但不是每个long都可以无损地转换为字节。然而,即使是Object类型Byte和Long也不是相互继承的。你只是没有得到一个警告,因为
byte s = (byte) 42; long o = s; // no problem, no warning byte b = (byte) o; // written like casting
pzfprimi2#
字节在Java中是有符号的,所以值的范围是-128到127。当简单地截断为8位时,作为长的130的位模式是作为字节的-126的位模式。再举一个例子:
int x = 255; byte b = (byte) x; // b is now -1
lp0sw83n3#
你是说byte b = (byte)l吗Java的类型是有符号的,所以字节允许-128到+127之间的数字。
byte b = (byte)l
9rygscc14#
对于初学者要了解:1字节= 8位范围(从2的补码编号系统导出)= [-2(n-1)至2(n-1)-1],其中n是位数,因此范围为-128至127每当value递增超过最高可能的+ve值时,流程转到最低可能的-ve值。因此,在值达到127之后,流继续从-128到-127再到-126以覆盖130的总空间,并且因此o/p是-126
kxxlusnw5#
一个无符号字节包含0到255的值,所以数字130可以放在里面,但是当它是一个有符号字节时,它只能达到127,所以130不能正确存储。由于数字是以二进制补码格式存储的,因此如果数字大于127,则可以减去256。130大于127,因此130 - 256 = -126。还要记住,超过前8位的任何其他位都将丢失。如果您有一个长valLong = 257,即9位因此,当转换为字节时,它会丢失一些信息并变为值1(257,长为00000000_000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_00000001,但一个字节只能保存最后一部分:00000001.
5条答案
按热度按时间jyztefdp1#
一个字节是一个8位的序列,这使得2^8个case = 256。其中一半表示负数,即-128到-1。然后是0,大约一半,1到127表示正数。
130作为Int看起来像128 + 2,即:
然而,Byte只有8位,赋值只取它们原来的位,但只取最后一位:
第一位表示,它是一个负数。现在你需要加多少才能得到零?让我们逐步进行:
让我们做更大的步骤。只要在我们有0的地方加上1,但首先我们回到x:
现在出现了转折点:我们再加1,得到零(加上溢出)
如果(x+y)+ 1 = 0,则x+y = -1。有趣的是,负1不仅与设置了“负标志”('1000:0001')的1(0000:0001)相同,而且看起来完全不同。然而,第一个位置总是告诉你符号:1始终表示阴性。
但我们之前加了什么?
它的第一个位置没有1,所以它是一个正值,我们知道如何解构它吗?
现在很清楚了x+125 = -1 =〉x = -126
您可以想象这些值,组织成一个圆圈,顶部是0(正午时分)和正值,就像从0到5的时钟一样排列(但到了127),以及底部的转折点(127 + 1 =〉-128 [sic!].)现在你可以顺时针继续,加上1会导致-127,-126,-125,... -3,-2,-1(在11点钟方向),最后又是0。
对于更大的数字(small,int,long),采用更大的时钟,0总是在顶部,最大值和最小值总是在底部。但是即使是一个字节也太大了,无法制作图片,所以我制作了一个半字节的时钟:
你可以很容易地填补图片中的漏洞,这是微不足道的!
顺便说一句:整个过程并不叫转换。转换只在对象之间使用。如果你有一些东西,真实的上是一个子类型:
这仅仅是一个赋值,因为字符串(总是)是一个对象。不涉及转换。
这是一个转换。转换到更具体的类型。不是每个对象都是String。与整数提升有一点关系,因为每个字节都可以无损地转换为long,但不是每个long都可以无损地转换为字节。然而,即使是Object类型Byte和Long也不是相互继承的。
你只是没有得到一个警告,因为
pzfprimi2#
字节在Java中是有符号的,所以值的范围是-128到127。
当简单地截断为8位时,作为长的130的位模式是作为字节的-126的位模式。
再举一个例子:
lp0sw83n3#
你是说
byte b = (byte)l
吗Java的类型是有符号的,所以字节允许-128到+127之间的数字。
9rygscc14#
对于初学者要了解:1字节= 8位范围(从2的补码编号系统导出)= [-2(n-1)至2(n-1)-1],其中n是位数,因此范围为-128至127
每当value递增超过最高可能的+ve值时,流程转到最低可能的-ve值。
因此,在值达到127之后,流继续从-128到-127再到-126以覆盖130的总空间,并且因此o/p是-126
kxxlusnw5#
一个无符号字节包含0到255的值,所以数字130可以放在里面,但是当它是一个有符号字节时,它只能达到127,所以130不能正确存储。
由于数字是以二进制补码格式存储的,因此如果数字大于127,则可以减去256。130大于127,因此130 - 256 = -126。
还要记住,超过前8位的任何其他位都将丢失。如果您有一个长valLong = 257,即9位因此,当转换为字节时,它会丢失一些信息并变为值1(257,长为00000000_000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_00000001,但一个字节只能保存最后一部分:00000001.