将 64 位数据转换为带符号的长值
Convert 64bit data to signed long value
我有这样的东西:
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)
我想将它们组合起来并在 Java 中形成一个 long 值。怎么做?
这样可以转换吗?
结果 = 0 + (0 x 2^16) + (0 x 2^16) + (124 x 2^32) + (5127 x 2^48)
即
结果=字节[3] + (字节[2] x 2^16) + (字节[1] x 2^32) + (字节[0] x 2^48)
编辑:让我试着解释得更好。当我打开工具 ModScan32 并连接到我的设备时,我看到了一些寄存器。在这个工具中有不同种类的选项如何显示数据。其中之一是将它们表示为二进制或十进制。当我选择二进制或十进制时,我得到的值与上面示例中的值相同。当我用我的软件读取这些数据时,我得到了完全相同的十进制值(转换后的值)。现在我的问题是,是否有必要将数据保存在 4 个 16 位寄存器中,并且我知道它们的十进制值,从寄存器中组合这些值并获得实际值的正确方法是什么?
你的想法基本没问题。有几点需要注意。
我相信你所追求的结果是 0001010000110100000000000111110000000000000000000000000000000000
。
这是一个无效的尝试:
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
表示左移48位,应该够了吧? |
是按位逻辑或,它将任一操作数中的 1 位填充到结果的相同位位置。如果您愿意,可以使用 +
。
这会打印:
10100001101000000000001111100
我们只有结果的前 32 位,这还不够好。尝试阅读时,请注意 Long.toBinaryString()
不包含前导零。想象一下数字前面有 3 个零。
但是发生了什么?最后 32 位到哪里去了?即使它们全为零。问题是我们在 int
s 中进行计算,它们是 32 位,而不是 64 位。编辑:我之前的解释在这一点上并不完全正确。真相是:在int
上做<<
时,只考虑右操作数的后5位,所以由于48在二进制中是110000,所以只用了10000,所以移位是一样的作为 << 16
。类似地 << 32
与 << 0
相同,完全没有移位。所以 registers[0]
和 [1]
最终出现在错误的位位置。当您知道时,解决方案很简单:我们需要在 进行计算之前转换为 long
。现在使用右操作数的最后6位,所以48和32理解为48和32:
long result = ((long) registers[0]) << 48 | ((long) registers[1]) << 32 | registers[2] << 16 | registers[3];
这次我们得到
1010000110100000000000111110000000000000000000000000000000000
同样,假设前面有 3 个零位,一切都符合预期。
还有一件事。假设您从寄存器中得到一个负值,例如:
int[] registers = { 5172, -124, 0, 0 };
刚才的计算现在给了我们
11111111111111111111111111000010000000000000000000000000000000000
这次打印的是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
是 16 个 1 位,而 &
是按位逻辑“与”,仅在两个操作数都为 1 位的位置给出结果中的 1 位。现在 -124 被屏蔽为 1111111110000100
所以结果是预期的:
1010000110100111111111000010000000000000000000000000000000000
应该可以了。
我有这样的东西:
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)
我想将它们组合起来并在 Java 中形成一个 long 值。怎么做?
这样可以转换吗?
结果 = 0 + (0 x 2^16) + (0 x 2^16) + (124 x 2^32) + (5127 x 2^48)
即
结果=字节[3] + (字节[2] x 2^16) + (字节[1] x 2^32) + (字节[0] x 2^48)
编辑:让我试着解释得更好。当我打开工具 ModScan32 并连接到我的设备时,我看到了一些寄存器。在这个工具中有不同种类的选项如何显示数据。其中之一是将它们表示为二进制或十进制。当我选择二进制或十进制时,我得到的值与上面示例中的值相同。当我用我的软件读取这些数据时,我得到了完全相同的十进制值(转换后的值)。现在我的问题是,是否有必要将数据保存在 4 个 16 位寄存器中,并且我知道它们的十进制值,从寄存器中组合这些值并获得实际值的正确方法是什么?
你的想法基本没问题。有几点需要注意。
我相信你所追求的结果是 0001010000110100000000000111110000000000000000000000000000000000
。
这是一个无效的尝试:
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
表示左移48位,应该够了吧? |
是按位逻辑或,它将任一操作数中的 1 位填充到结果的相同位位置。如果您愿意,可以使用 +
。
这会打印:
10100001101000000000001111100
我们只有结果的前 32 位,这还不够好。尝试阅读时,请注意 Long.toBinaryString()
不包含前导零。想象一下数字前面有 3 个零。
但是发生了什么?最后 32 位到哪里去了?即使它们全为零。问题是我们在 int
s 中进行计算,它们是 32 位,而不是 64 位。编辑:我之前的解释在这一点上并不完全正确。真相是:在int
上做<<
时,只考虑右操作数的后5位,所以由于48在二进制中是110000,所以只用了10000,所以移位是一样的作为 << 16
。类似地 << 32
与 << 0
相同,完全没有移位。所以 registers[0]
和 [1]
最终出现在错误的位位置。当您知道时,解决方案很简单:我们需要在 进行计算之前转换为 long
。现在使用右操作数的最后6位,所以48和32理解为48和32:
long result = ((long) registers[0]) << 48 | ((long) registers[1]) << 32 | registers[2] << 16 | registers[3];
这次我们得到
1010000110100000000000111110000000000000000000000000000000000
同样,假设前面有 3 个零位,一切都符合预期。
还有一件事。假设您从寄存器中得到一个负值,例如:
int[] registers = { 5172, -124, 0, 0 };
刚才的计算现在给了我们
11111111111111111111111111000010000000000000000000000000000000000
这次打印的是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
是 16 个 1 位,而 &
是按位逻辑“与”,仅在两个操作数都为 1 位的位置给出结果中的 1 位。现在 -124 被屏蔽为 1111111110000100
所以结果是预期的:
1010000110100111111111000010000000000000000000000000000000000
应该可以了。