如何在 Java 中执行无符号到有符号的转换?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3935304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to perform unsigned to signed conversion in Java?
提问by Brad Hein
Say I read these bytes: "6F D4 06 40" from an input device. The number is a longitude reading in MilliArcSeconds format. The top bit (0x80000000) is basically always zero and is ignored for this question.
假设我从输入设备读取了这些字节:“6F D4 06 40”。该数字是 MilliArcSeconds 格式的经度读数。最高位 (0x80000000) 基本上始终为零,此问题将被忽略。
I can easily convert the bytes to an unsignedinteger: 1876166208
我可以轻松地将字节转换为无符号整数:1876166208
But how do I convert that unsigned value into its final form of 31-bit signed-integer?
但是如何将该无符号值转换为其最终形式的 31 位有符号整数呢?
So far all I've come up with is:
到目前为止,我想出的是:
- if value & 0x40000000 then it's actually negative, need to convert it
- If it's negative, strip the top bit and do something with the remaining bits...
- 如果 value & 0x40000000 那么它实际上是负数,需要转换它
- 如果它是负数,去掉顶部的位并用剩余的位做一些事情......
So I can tell if it's a negative number, but in order to know what value the negative number is, I have to do something with the remaining bits - a one's compliment? How do I do that in Java?
所以我可以判断它是否是一个负数,但是为了知道负数是什么值,我必须对剩余的位做一些事情 - 一个人的恭维?我如何在 Java 中做到这一点?
Another way to put the question is, how do I convert an unsigned integer into a 31-bit signed integer in Java?
提出问题的另一种方法是,如何在 Java 中将无符号整数转换为 31 位有符号整数?
Thank you!
谢谢!
采纳答案by Mark Peters
The answer depends on what the lower 31 bits of your input are meant to represent.
答案取决于您输入的低 31 位的含义。
int input = 0x6FD40640 & 0x7FFFFFFF; //strip top bit; only here for clarity
Unsigned input: 0x6FD40640 == 1876166208
无符号输入: 0x6FD40640 == 1876166208
Two's complement (desired output: -271317440)
二进制补码(所需输出:-271317440)
A two's complementinteger is one where -1 has all bits set, and lower negatives number count down from there. The first bit still acts as a sign bit.
一个二进制补码整数是一个 -1 设置了所有位,并且从那里向下计数的较低负数。第一位仍然充当符号位。
1000 -> -8
1001 -> -7
...
1110 -> -2
1111 -> -1
0000 -> 0
0001 -> 1
If the lower 31 bits represent a two's complement integer, then I think you should just be able to do this:
如果低 31 位表示二进制补码整数,那么我认为您应该能够做到这一点:
input = (input << 1) >> 1;
That's because Java stores integers in two's complement internally: all we do is shift left and then shift back right (signed) so that the sign bit is picked up and the integer goes from 31 bits to 32 bits.
那是因为 Java 在内部以二进制补码形式存储整数:我们所做的只是左移然后右移(有符号),以便拾取符号位并且整数从 31 位变为 32 位。
One's complement (desired output: -802424384)
一个的补码(期望输出:-802424384)
A one's complementnumber representation is one where the first bit is a dedicated sign bit, and the remaining bits represent the magnitude. The lower bits of -100 will be the same as the lower bits of 100:
一个1 的补码表示是第一个位是专用符号位,其余位表示幅度。-100 的低位将与 100 的低位相同:
1111 -> -7
1110 -> -6
...
1001 -> -1
1000 -> -0 (anomoly)
0000 -> 0
0001 -> 1
If the lower 31 bits represent a one's complementinteger (that is, a sign bit followed by 30 bits representing an unsigned magnitude), then you need to convert it into two's complement so that Java extracts the value properly. To do this you just need to extract the lower 30 bits and multiply by -1:
如果低 31 位表示整数的补码(即一个符号位后跟 30 位表示无符号量),那么您需要将其转换为二进制补码,以便 Java 正确提取该值。为此,您只需要提取低 30 位并乘以 -1:
if ( input & 0x40000000 ) {
input = (input & 0x3FFFFFFF) * -1;
}
You said in the question's comments that after converting to degrees (dividing by 3600000) you get around -75.36. When I divide -271317440 by 3600000 I get -75.36595555555556, so I'm guessing your input format is two's complement, so my first and original answer was correct.
您在问题的评论中说,转换为度数(除以 3600000)后,您会得到大约 -75.36。 当我将 -271317440 除以 3600000 时,我得到 -75.36595555555556,所以我猜你的输入格式是二进制补码,所以我的第一个和原始答案是正确的。
回答by Brad Hein
Reading an unsigned integer as signed is a matter of identifying whether the most significant bit (negative flag) is set, and if so, flip all bits of the number (thus clearing the most significant bit, and switching the number to its negative representation. When performing the aforementioned process you must also make note of the fact that the resultant number is a negative.
读取有符号的无符号整数是确定是否设置了最高有效位(负标志)的问题,如果设置了,则翻转数字的所有位(从而清除最高有效位,并将数字切换为其负表示。在执行上述过程时,您还必须注意结果数字是负数这一事实。
// Convert the hex bytes to an unsigned integer
long MAS = Integer.ValueOf("6F D4 06 40".replace (" ",""),16);
boolean isLongitudeNegative = false;
// Is the negative-bit set? If so, strip it and toggle all bits.
if (MAS & 0x40000000 > 0) {
// then it's negative, so strip the negative bit and flip all the other bits
MAS ^= 0xFFFFFFFF;
// Throw away the unused bit.
MAS &= 0x7FFFFFFF;
isLongitudeNegative = true;
}
// Now convert from MAS to degrees minutes seconds
String DMS = convertMASToDMS(isLongitudeNegative,MAS);