假设我从输入设备读取了以下字节:" 6F D4 06 40"。 该数字是MilliArcSeconds格式的经度读数。 最高位(0x80000000)基本上始终为零,因此该问题被忽略。
我可以轻松地将字节转换为无符号整数:1876166208
但是,如何将该无符号值转换为最终形式的31位有符号整数?
到目前为止,我只想出了:
如果value&0x40000000那么它实际上是负数,需要将其转换
如果是负数,则剥离最高位,然后对其余位进行一些处理...
因此,我可以判断它是否为负数,但是为了知道负数是什么值,我必须对其余的位做些什么-一个恭维吗? 如何在Java中做到这一点?
提出问题的另一种方法是,如何在Java中将无符号整数转换为31位带符号整数?
谢谢!
我想我在回答中误解了你的问题。您可以根据示例输入说出想要带符号整数的值是什么吗?你从没说过
输入:" 6F D3 FD 45"。输出:大约-75.366465。我说大概是因为我找到了一个地点并留在那里收集数据,同时使用GPS测量了位置。因此,上面的经度(-75.366465)应该接近,但可能不完全相同,与上述十六进制字节转换为有符号整数(并执行MAS至度数转换)的值相同。我试图找到一种方法来使用Java从十六进制字节转换为带符号的int
MAS至学位:除以3,600,000。
越来越近...去除"负位"的实际读数:" 2F D3 FD 45" ...将其与" 10 2C 00 EA"的-75.366465的预期MAS值进行比较...如果我翻转,则前22位匹配1到0和0到1(XOR)。我认为这可能是诀窍-需要翻转所有位...我可以使用XOR做到这一点...
@Mark-您是正确的。我很抱歉。
答案取决于输入的低31位表示什么。
int input = 0x6FD40640 & 0x7FFFFFFF; //strip top bit; only here for clarity
无符号输入:0x6FD40640 == 1876166208
二进制补码(期望输出:-271317440)
二进制补码整数是一个整数,其中-1的所有位均已设置,而较低的负数从此开始递减计数。第一位仍然充当符号位。
1000 -> -8
1001 -> -7
...
1110 -> -2
1111 -> -1
0000 -> 0
0001 -> 1
如果低31位代表二进制补码整数,那么我认为您应该能够做到这一点:
input = (input << 1) >> 1;
这是因为Java在内部将整数存储为二进制补码:我们要做的就是向左移然后向右移(带符号),以便选择符号位并将整数从31位变为32位。
一个补码(期望的输出:-802424384)
一个人的补码表示是其中第一位是专用符号位,其余位表示幅度的人。 -100的低位与100的低位相同:
1111 -> -7
1110 -> -6
...
1001 -> -1
1000 -> -0 (anomoly)
0000 -> 0
0001 -> 1
如果低31位表示一个补码整数(即一个符号位,后跟30个表示无符号幅度的位),则需要将其转换为二进制补码,以便Java正确提取该值。为此,您只需要提取低30位并乘以-1:
if ( input & 0x40000000 ) {
input = (input & 0x3FFFFFFF) * -1;
}
您在问题的评论中说,转换为度(除以3600000)后,您可以获得-75.36左右。当我将-271317440除以3600000时,我得到-75.36595555555556,因此我猜测您的输入格式为二进制补码,因此我的第一个和原始答案是正确的。
看起来会成功。但是不确定& 0x7FFFFFFF是否必要。
似乎&7fffffff和左/右移位做了同样的事情(删除最左边的最高位)?我正在努力获取一些示例数据,因此我们可以对其进行测试
@Alison:不能仅仅用来证明输入只是低31位,而高位是无关紧要的。第二行是我要显示的内容,但是Brad尚未确认这是否是所需的输出。
@Brad:只需按&7FFFFFFF进行"与"运算就可以清除最高位。这会向左移动,但以符号扩展的方式向右移动。换句话说,它用第二位填充第一位。但是我再次需要查看您想要的输出是什么...我不知道31个低位应该代表什么。
为什么这个答案被投票否决?它根本没有解决这个问题。请重新阅读问题!
将无符号整数读取为带符号整数是确定是否设置了最高有效位(负标志)的问题,如果是,则翻转数字的所有位(从而清除最高有效位,然后将数字切换为负数)。执行上述过程时,还必须注意结果为负数的事实。
// 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);
很抱歉爆发。这个答案是否最终满足了您的要求?如果是这样,请随时接受。唯一的建议是您可能会发现MAS = ~MAS是切换MAS位的更清晰的方法。因此,在给出此解决方案的情况下,我假设输入的低31位表示一个31位的补码整数,而您试图提取该值?那是您要解决的问题吗?
再次检查我的答案。我很确定我的原始答案是正确的。当我将转换应用于您的样本输入,然后除以3600000时,我得到-75.369555,这是您的预期输出。当我进行转换时,我会得到-222的提示。