在 Java 中将 long 转换为字节

Posted

技术标签:

【中文标题】在 Java 中将 long 转换为字节【英文标题】:Casting long to byte in Java 【发布时间】:2011-08-03 04:55:23 【问题描述】:

我无法理解以下内容:

在java中,

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

如果我打印 b 的值,为什么会得到 -126? long l的位表示是什么?

【问题讨论】:

我认为代码甚至无法编译 【参考方案1】:

一个字节是一个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) 

但是,字节只有 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。

对于较大的数字(small、int、long)需要更大的时钟,零总是在顶部,最大值和最小值总是在底部。但是即使是一个字节也太大了,无法制作图片,所以我制作了一个半字节,一个半字节:

你可以轻松填补图片中的漏洞,很简单!

顺便说一句:整件事不叫casting。铸造只在对象之间使用。如果你有一些东西,它实际上是一个子类型:

 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 

【讨论】:

这应该是公认的答案,非常有用。感谢您的努力!【参考方案2】:

字节在 Java 中签名 - 因此值的范围是 -128 到 127(含)。

将 130 作为 long 的位模式,当简单地截断为 8 位时,就是 -126 作为一个字节的位模式。

再举一个例子:

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

【讨论】:

谢谢乔恩。但是 l 中的位值是多少?二进制中的 130 等于 '10000010' 那么这里的截断是如​​何发生的呢? l 中被截断为-126 .. 的值是多少? @Pan:这正是位模式……在 2 的补码 (en.wikipedia.org/wiki/Two's_complement) 中,8 位值是 -126。你明白我的例子,'11111111' 以 -1 结尾吗?原理完全一样。【参考方案3】:

你是说byte b = (byte)l

Java 的类型是有符号的,因此字节允许 -128 和 +127 之间的数字。

【讨论】:

【参考方案4】:

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

只要值的增量超过可能的最高 +ve 值,流量就会转到可能的最低 -ve 值。

所以在值达到 127 之后,流量从 -128 继续到 -127 到 -126 覆盖 130 的总空间,因此 o/p 为 -126

【讨论】:

我认为你的意思是字节的范围是 -128 到 127。int 的范围是 -2147483648 到 2147483647。 是的..我的意思是字节 您的标题具有误导性,您的帖子中没有问题。

以上是关于在 Java 中将 long 转换为字节的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java中将String转换为long?

如何在java中将十六进制字符串转换为long?

java中将一个double类型的数强制转换为long 型是四舍五入吗?

如何在 Spring Boot 应用程序中将 java lang long 转换为实体类

在java中将字符串转换为字节[重复]

在 JavaCard 中将字节转换为短字节