在Java中将长整型转换为字节

4
我无法理解以下内容:

在Java中,

long l = 130L;  
byte b = (byte)l;

如果我打印变量b的值,为什么输出是-126?long l的位表示是什么?

2
我认为那段代码甚至无法编译。 - OscarRyz
5个回答

15

一个字节是8个比特的序列,共有2^8种情况=256。其中一半表示负数,即-128至-1。然后是0,另一半从1到127表示正数。

整数130看起来像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,得到的结果为零(加上溢出)。

1111:1111 (x + y) + 
0000:0001 1
--------- 
0000:0000 0

如果 (x+y) + 1 = 0,那么 x+y = -1。有趣的是,减去 1 并不仅仅是将 1(0000:0001)带有“负标志”的值('1000: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),请使用更大的时钟,零始终在顶部,最大值和最小值始终在底部。但即使是一个字节也太大了,无法制作图片,所以我制作了一个半字节(nibble)的图片:

bitpatterns of integer, arranged in circle form

你可以轻松地填补图片上的空白,这很简单!

顺便说一下:整个过程不叫casting。Casting只用于对象之间。如果你有一个真正的子类型:

 Object o = new String ("casting or not?"); 

这只是一个简单的赋值操作,因为String(字符串)(始终)是一个对象。没有涉及到类型转换。

 String s = (String) o; 

这是一种类型转换,将对象转换为更具体的类型。并非所有对象都是字符串类型。与整数提升有些关系,因为每个字节都可以无损地转换为长整型,但不是每个长整型都能转换为字节型。然而,即使Byte和Long这样的对象类型也不彼此继承。

你只是不会收到警告,因为

byte s = (byte) 42;
long o = s; // no problem, no warning
byte b = (byte) o; // written like casting 

这应该是被接受的答案,非常有信息量。感谢您的努力! - Ahmad Sanie

9

在Java中,字节是有符号的,因此值的范围为-128到127(包括两个端点)。

当将长整型数值130的位模式简单地截断为8位时,其位模式就是作为字节时数值-126的位模式。

再举一个例子:

int x = 255;
byte b = (byte) x; // b is now -1

谢谢Jon。但是l中的位值是多少?130在二进制中等于'10000010',那么这里的截断是如何发生的?哪个值在l中被截断成为-126..? - Pan

2
你是指 byte b = (byte)l 吗?
Java的类型是有符号的,因此字节允许介于-128和+127之间的数字。

1

对于初学者理解: 1字节 = 8位 范围(来自2的补码系统)= [-2^(n-1)到2^(n-1)-1],其中n是位数 所以范围是-128到127

每当值增加超过最大可能的正值时,流程就会转到最小可能的负值。

因此,在值达到127后,流程继续从-128到-127到-126, 覆盖了总空间130,因此输出为-126


我认为你的意思是字节范围为-128到127。整数范围为-2147483648到2147483647。 - Hitobat
是的,我是指字节。 - unknown
你的标题有误导性,而且在你的帖子中没有问题。 - Vladimir Vaschenko

0

无符号字节可以保存0到255的值,因此数字130可以放在其中,但当它是有符号字节时,它只能达到127,所以130将无法正确存储。

由于数字以二进制补码格式存储,如果数字大于127,则可以减去256。130大于127,因此130-256=-126。

还要记住,除了第一个8位之外的任何其他位都将丢失。如果您有一个长valLong = 257,即9位,那么在转换为字节时会丢失一些信息,并变成1的值(257作为长整型是00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000001,但字节只能保存最后一部分:00000001)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接