将64位数据转换为有符号长值

时间:2022-02-24 16:24:30

I have something like this:

我有这样的事情:

byte[0] = 0001 0100 0011 0100  (dec value: 5172)  
byte[1] = 0000 0000 0111 1100  (dec value: 124)  
byte[2] = 0000 0000 0000 0000  (dec value: 0)  
byte[3] = 0000 0000 0000 0000  (dec value: 0)

I would like to combine them and make one long value in Java. How to do that?

我想将它们组合起来,并在Java中创建一个长值。怎么做?

Can it be converted on this way?

可以这样转换吗?

result = 0 + (0 x 2^16) + (0 x 2^16) + (124 x 2^32) + (5127 x 2^48)

result = 0 +(0 x 2 ^ 16)+(0 x 2 ^ 16)+(124 x 2 ^ 32)+(5127 x 2 ^ 48)

ie.

result = byte[3] + (byte[2] x 2^16) + (byte[1] x 2^32) + (byte[0] x 2^48)

result = byte [3] +(byte [2] x 2 ^ 16)+(byte [1] x 2 ^ 32)+(byte [0] x 2 ^ 48)

Edit: Let me try to explain better. When I open tool ModScan32 and connect to my device I see some registers. In this tool there are different kind of options how to show data. One of them are to represent them as binary or decimal. When I choose binary or decimal I get values as they are in my example above. When I read this data with my software I get exactly the same (converted values) in the decimal. Now my question is if it is necessary to hold data in 4 16 bit registers and i know their decimal values what is the proper way to combine those values from registers and get real value?

编辑:让我试着更好地解释一下。当我打开工具ModScan32并连接到我的设备时,我看到一些寄存器。在此工具中,有不同类型的选项如何显示数据。其中一个是将它们表示为二进制或十进制。当我选择二进制或十进制时,我得到的值与上面的例子中一样。当我用我的软件读取这些数据时,我得到十进制的完全相同(转换值)。现在我的问题是,是否有必要在4个16位寄存器中保存数据,并且我知道它们的十进制值是什么方法将这些值与寄存器组合并获得实际值?

1 个解决方案

#1


1  

Your idea is basically OK. There are a few things to be aware of.

你的想法基本上没问题。有几点需要注意。

I believe the result you are after in your case is 0001010000110100000000000111110000000000000000000000000000000000.

我相信你所处理的结果是0001010000110100000000000111110000000000000000000000000000000000。

Here’s an attempt that does not work:

这是一个不起作用的尝试:

    int[] registers = { 5172, 124, 0, 0 };
    long result = registers[0] << 48 | registers[1] << 32 | registers[2] << 16 | registers[3];
    System.out.println(Long.toBinaryString(result));

<< 48 means shift 48 bits to the left, that should be good enough, right? | is a bitwise logical or, it fills the 1 bits from either operand into the same bit posistion of the result. You could use + instead if you preferred.

<< 48表示向左移48位,应该足够好吧? |是按位逻辑或者,它将任一操作数中的1位填充到结果的相同位位置。如果您愿意,可以使用+代替。

This prints:

10100001101000000000001111100

We only have the first 32 bits of the result, that’s not good enough. When trying to read it, note that Long.toBinaryString() does not include leading zeroes. Just imagine 3 zeroes in front of the number.

我们只有结果的前32位,这还不够好。在尝试阅读时,请注意Long.toBinaryString()不包含前导零。想象一下这个数字前面有3个零。

But what went worng? Where did the last 32 bits go? Even when they were all zeroes. The problem is that we are doing the calculation in ints, they are 32 bits, not 64. EDIT: My previous explanation was not entirely correct on this point. The truth is: When doing << on an int, only the last 5 bits of the right operand are considered, so since 48 is 110000 in binary, only 10000 is used, so the shift is the same as << 16. Similarly << 32 is the same as << 0, no shift at all. So registers[0] and [1] have ended up in the wrong bit posistion. The solution is easy when you know it: we need to convert to long before doing the calculation. Now the last 6 bits of the right operand are used, so 48 and 32 are understood as 48 and 32:

但到底是什么?最后32位去了哪里?即使它们都是零。问题是我们用int进行计算,它们是32位,而不是64位。编辑:我之前的解释在这一点上并不完全正确。事实是:当对int执行时,只考虑右操作数的最后5位,因此48是二进制的110000,只使用10000,所以移位与<< 16相同。 <32与<< 0相同,完全没有移位。因此寄存器[0]和[1]最终位于错误的位置。当你知道它时,解决方案很简单:在进行计算之前我们需要转换为很久。现在使用右操作数的最后6位,因此48和32被理解为48和32:

    long result = ((long) registers[0]) << 48 | ((long) registers[1]) << 32 | registers[2] << 16 | registers[3];

This time we get

这次我们得到了

1010000110100000000000111110000000000000000000000000000000000

Again, imagine 3 zero bits in front and all is as expected.

再次,想象前面的3个零位,所有都是预期的。

There is one more thing. Say you got a negative value from a register, for example:

还有一件事。假设您从寄存器中获得负值,例如:

    int[] registers = { 5172, -124, 0, 0 };

The calculation that just worked now gives us

现在正在运行的计算给了我们

1111111111111111111111111000010000000000000000000000000000000000

This time there are 64 bits printed, so it’s easy to see there are too many 1s in the beginning. They come from the int representation of -124. The solution is to mask them out:

这次有64位打印,因此很容易看到开头有太多的1。它们来自-124的int表示。解决方案是掩盖它们:

    int[] registers = { 5172, -124, 0, 0 };
    long result = ((long) registers[0] & 0xFFFF) << 48
            | ((long) registers[1] & 0xFFFF) << 32 
            | (registers[2] & 0xFFFF) << 16 
            | (registers[3] & 0xFFFF);
    System.out.println(Long.toBinaryString(result));

0xFFFF is 16 1 bits, and & is the bitwise logical ‘and’, giving a 1 bit in the result only in positions where both operands have a 1 bit. Now -124 gets masked to 1111111110000100 so the result is the expected:

0xFFFF为16 1位,&是按位逻辑'和',仅在两个操作数均为1位的位置给出1位结果。现在-124被掩盖到1111111110000100所以结果是预期的:

1010000110100111111111000010000000000000000000000000000000000

That should do it.

应该这样做。

#1


1  

Your idea is basically OK. There are a few things to be aware of.

你的想法基本上没问题。有几点需要注意。

I believe the result you are after in your case is 0001010000110100000000000111110000000000000000000000000000000000.

我相信你所处理的结果是0001010000110100000000000111110000000000000000000000000000000000。

Here’s an attempt that does not work:

这是一个不起作用的尝试:

    int[] registers = { 5172, 124, 0, 0 };
    long result = registers[0] << 48 | registers[1] << 32 | registers[2] << 16 | registers[3];
    System.out.println(Long.toBinaryString(result));

<< 48 means shift 48 bits to the left, that should be good enough, right? | is a bitwise logical or, it fills the 1 bits from either operand into the same bit posistion of the result. You could use + instead if you preferred.

<< 48表示向左移48位,应该足够好吧? |是按位逻辑或者,它将任一操作数中的1位填充到结果的相同位位置。如果您愿意,可以使用+代替。

This prints:

10100001101000000000001111100

We only have the first 32 bits of the result, that’s not good enough. When trying to read it, note that Long.toBinaryString() does not include leading zeroes. Just imagine 3 zeroes in front of the number.

我们只有结果的前32位,这还不够好。在尝试阅读时,请注意Long.toBinaryString()不包含前导零。想象一下这个数字前面有3个零。

But what went worng? Where did the last 32 bits go? Even when they were all zeroes. The problem is that we are doing the calculation in ints, they are 32 bits, not 64. EDIT: My previous explanation was not entirely correct on this point. The truth is: When doing << on an int, only the last 5 bits of the right operand are considered, so since 48 is 110000 in binary, only 10000 is used, so the shift is the same as << 16. Similarly << 32 is the same as << 0, no shift at all. So registers[0] and [1] have ended up in the wrong bit posistion. The solution is easy when you know it: we need to convert to long before doing the calculation. Now the last 6 bits of the right operand are used, so 48 and 32 are understood as 48 and 32:

但到底是什么?最后32位去了哪里?即使它们都是零。问题是我们用int进行计算,它们是32位,而不是64位。编辑:我之前的解释在这一点上并不完全正确。事实是:当对int执行时,只考虑右操作数的最后5位,因此48是二进制的110000,只使用10000,所以移位与<< 16相同。 <32与<< 0相同,完全没有移位。因此寄存器[0]和[1]最终位于错误的位置。当你知道它时,解决方案很简单:在进行计算之前我们需要转换为很久。现在使用右操作数的最后6位,因此48和32被理解为48和32:

    long result = ((long) registers[0]) << 48 | ((long) registers[1]) << 32 | registers[2] << 16 | registers[3];

This time we get

这次我们得到了

1010000110100000000000111110000000000000000000000000000000000

Again, imagine 3 zero bits in front and all is as expected.

再次,想象前面的3个零位,所有都是预期的。

There is one more thing. Say you got a negative value from a register, for example:

还有一件事。假设您从寄存器中获得负值,例如:

    int[] registers = { 5172, -124, 0, 0 };

The calculation that just worked now gives us

现在正在运行的计算给了我们

1111111111111111111111111000010000000000000000000000000000000000

This time there are 64 bits printed, so it’s easy to see there are too many 1s in the beginning. They come from the int representation of -124. The solution is to mask them out:

这次有64位打印,因此很容易看到开头有太多的1。它们来自-124的int表示。解决方案是掩盖它们:

    int[] registers = { 5172, -124, 0, 0 };
    long result = ((long) registers[0] & 0xFFFF) << 48
            | ((long) registers[1] & 0xFFFF) << 32 
            | (registers[2] & 0xFFFF) << 16 
            | (registers[3] & 0xFFFF);
    System.out.println(Long.toBinaryString(result));

0xFFFF is 16 1 bits, and & is the bitwise logical ‘and’, giving a 1 bit in the result only in positions where both operands have a 1 bit. Now -124 gets masked to 1111111110000100 so the result is the expected:

0xFFFF为16 1位,&是按位逻辑'和',仅在两个操作数均为1位的位置给出1位结果。现在-124被掩盖到1111111110000100所以结果是预期的:

1010000110100111111111000010000000000000000000000000000000000

That should do it.

应该这样做。