Java中的二进制表示

11

我发现在Java中理解和处理二进制表示法很困难:

在Jon Skeet用户的帮助下,我明白了应该这样构建二进制表示法。

以下是代码示例:

public class chack {

public static void main(String[] args) {
    int num2=2;
    int num3=3;
    int num4=4;
    int num1=1;
    int nirbinary = (num1 << 24) | (num2 << 16) | (num3 << 8) | num4;
    System.out.println(nirbinary);
    String nir=  Integer.toBinaryString(nirbinary);
    System.out.println(nir);
    }
}

几个问题:

  1. 如何从一个已经以二进制形式表示的int中获取num1(例如)
  2. 为什么当我打印nirbinary时会得到16909060,它代表什么意思? 如何从一个已经以二进制形式表示的int中获取num1(例如)?

谢谢


你得到的数字是不是2^24 + 22^16 + 32^8 + 4? - Ingo
7个回答

28

我不完全确定你需要什么,因此我将解释如何在Java中将整数转换为二进制字符串。

你可以像这样从整数获取二进制字符串:

int i = 1234;
String binString = Integer.toBinaryString(i);

你可以通过以下方式将字符串转换回整数:

int iNew = Integer.parseInt(binString, 2);

请注意 Integer.parseInt() 的第二个参数是数字的所需进制。2 表示二进制,8 表示八进制,10 表示十进制等。


1
谢谢您的评论。我不想使用字符串工作。我只想使用这种二进制表示,并且更有趣的是,我想知道如何从这个int nirbinary中获取num1。 - Unknown user
啊,好的。那么其他的答案可能会更有帮助 :D - jberg

14

16909060代表数字16909060。

它等于(1 * 224) + (2 * 216) + (3 * 28) + 4

要重新获取num1,只需对结果执行相同数量的右移位操作,并掩盖其他字节(对于 num1 (*)不总是必要的,但对于其他操作数则必须这样做):

int num1 = nirbinary >> 24 & 0xFF;
int num2 = nirbinary >> 16 & 0xFF;
int num3 = nirbinary >> 8 & 0xFF;
int num4 = nirbinary & 0xFF;
请注意,nirbinary不是“二进制表示”。更准确地说:它与num1num2num3num4一样,没有更多或更少的二进制:所有数字(和字符、布尔值等)都以二进制形式存储。
(*) 请注意,如果num1 > 127,则您需要使用>>>来进行正确的右移,或者使用& 0xFF以确保恢复正确的值。 >>>>>之间的区别在于插入到值的“左侧”的“新”位:使用>>它们将取决于最高值位(称为符号扩展),而使用>>>它们始终为0。

谢谢您的评论。您能解释一下写& 0xFF的含义吗?这与仅写num1 = nirbinary >> 24有何区别,正如此处所建议的那样? - Unknown user
3
@Nir: 对于num1来说没有区别(因为num1存储在nirbinary的最高8位中)。但是对于num2num3num4,这个操作则会清除掉存储其他数字的更高位(例如,如果你执行nirbinary >> 16,你将获得一些包含num2在最低8位 以及 num1在接下来的8位中的值)。& 0xFF将所有比最低8位高的位都设置为零,有效地移除了其他值。 - Joachim Sauer

3
每个int都是一个数字,它不是二进制、十六进制或十进制,它只是一个数字。语句(num1 << 24) | (num2 << 16) | (num3 << 8) | num4;是对4个int进行二进制操作,生成另一个int。这并不会改变nirbinary的表示形式为二进制,因为nirbinary没有表示形式,因为(再次强调)它只是一个数字。 Integer.toBinaryString(nirbinary)返回nirbinary的二进制表示形式,这意味着“在二进制基础上,nibinary看起来像什么”。
如果您有一个字符串,其中包含一个数字的二进制表示形式,您可以使用Integer.parseint(yourbinaryrepresentation, yourbase);获取其值,例如- Integer.parseint(nir, 2); 还有一件事:
您不能总是从nirbinary中恢复出一个数字,因为您执行了不可逆的位操作,例如:
int i1 = 5;   //binary 0101
int i2 = 4;   //binary 0100
int i3 = i1 | i2;  //binary 0101

由于它们有一个共同的位,你无法识别每个变量(i1,i2),i3可能是对另外两个数字执行“或”操作的结果:

int i1 = 1;   //binary 0101
int i2 = 4;   //binary 0100
int i3 = i1 | i2;  //binary 0101

在您的情况下,如果每个数字都小于256,您可以使用以下操作将其反转:
int myoldnumber = (nirbinary >> previousShift) & 0xff;

例如,要检索num1,您可以执行以下操作:
int retrievedNum1 = (nirbinary >> 24) & 0xff;

3

这里不需要仅依赖于二进制或其他格式... 一个灵活的内置函数可用 它可以在您的程序中打印任何您想要的格式。

Integer.toString(int,representation);

Integer.toString(100,8)   // prints 144 --octal representation

Integer.toString(100,2)  // prints 1100100 --binary representation

Integer.toString(100,16) //prints 64  --Hex representation

Integer.toString(100,5) // prints 400  --Base 5

2
当处理位移和整数时,建议您以十六进制数字为基础思考,这通常会让生活变得更加容易。只需记住,8位表示1字节,1字节涵盖从0x00到0xFF的十六进制范围。
由于num1到num4小于10,因此它们的十进制表示等于它们的十六进制表示,即1 = 0x01,2 = 0x02等。 正如我告诉过你的:1字节是8位。在您的位移操作中,您总是要进行8的倍数位移。
所以,0x01 << 8 => 0x0100,0x01 << 16 => 0x010000,等等。
因此,您基本上只添加了零字节,这当然会增加值。接下来要做的是将它们进行“或”操作,即按位或。这意味着两个位域被修改,以便结果在某个位置具有1,如果至少一个输入值在那里有1,则结果为1。由于您的移位整数仅包含后面的零,因此按位或不过是将该值放在此处。
例如:
(0x01 << 8) | 0x02

0x01 << 8会生成0x0100。现在你只需用02替换最后的00,因为你或者他们:0x0102

如果您想重新创建原始int,则必须屏蔽int表示的部分(由于示例中部分不重叠,因此这很容易),然后将其移回。

例如:假设你生成了0x010203并且只想要0x02。现在,您必须掩码并将其移回0x010203>> 8,这将使02位于最后一部分。现在只需屏蔽此最后一部分0x0102&& 0xFF。这将将除最后8位之外的所有位设置为零


0
  1. 基本上是 1 * 2^24 + 2 * 2^16 + 3 * 2^8 + 4 = 16909060
  2. 你可以通过执行 num1 = nirbinary >> 24 来获取 num1。

0
  1. 你期望得到什么?
  2. 从int i中获取最高有效字节:

(i >> 24) & 0xff


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