如何在Java中执行无符号到有符号的转换?

如何在Java中执行无符号到有符号的转换?,java,type-conversion,signed,Java,Type Conversion,Signed,假设我从输入设备读取这些字节:“6Fd4 06 40”。该数字是以毫秒为单位的经度读数。顶部位(0x80000000)基本上始终为零,在这个问题中被忽略 我可以轻松地将字节转换为无符号整数:1876166208 但我如何将无符号值转换为最终形式的31位有符号整数呢 到目前为止,我想到的是: 如果值为&0x40000000,那么它实际上是负数,需要对其进行转换 如果是负数,去掉上面的一位,用剩下的一位做点什么 所以我可以判断它是否是一个负数,但是为了知道负数是什么值,我必须对剩余的位做些什么-一个

假设我从输入设备读取这些字节:“6Fd4 06 40”。该数字是以毫秒为单位的经度读数。顶部位(0x80000000)基本上始终为零,在这个问题中被忽略

我可以轻松地将字节转换为无符号整数:1876166208

但我如何将无符号值转换为最终形式的31位有符号整数呢

到目前为止,我想到的是:

  • 如果值为&0x40000000,那么它实际上是负数,需要对其进行转换
  • 如果是负数,去掉上面的一位,用剩下的一位做点什么
  • 所以我可以判断它是否是一个负数,但是为了知道负数是什么值,我必须对剩余的位做些什么-一个一的赞美?在Java中如何做到这一点

    另一种解决问题的方法是,在Java中如何将无符号整数转换为31位有符号整数


    谢谢大家!

    答案取决于输入的低31位代表什么

    int input = 0x6FD40640 & 0x7FFFFFFF; //strip top bit; only here for clarity
    
    无符号输入:
    0x6FD40640==1876166208

    两个补码(期望输出:-271317440) 2的补码整数是一个-1设置了所有位的整数,负数从那里开始倒数。第一位仍然充当符号位

    1000 -> -8
    1001 -> -7
    ...
    1110 -> -2
    1111 -> -1
    0000 ->  0
    0001 ->  1
    
    如果较低的31位表示2的补码整数,那么我认为您应该能够做到:

    input = (input << 1) >> 1;
    
    如果较低的31位表示一个补码整数(即,一个符号位后跟30位表示一个无符号的幅度),则需要将其转换为2的补码,以便Java正确提取值。为此,只需提取较低的30位并乘以-1:

    if ( input & 0x40000000 ) {
       input = (input & 0x3FFFFFFF) * -1;
    }
    

    你在问题的评论中说,在转换成学位(除以3600000)后,你会得到-75.36当我将-271317440除以3600000时,我得到了-75.3659555556,因此我猜您的输入格式是2的补码,因此我的第一个和原始答案是正确的。

    将无符号整数读取为有符号是一个识别是否设置了最高有效位(负标志)的问题,如果设置了,则翻转数字的所有位(从而清除最高有效位,并将数字转换为负数表示。执行上述过程时,还必须注意结果数字为负数

    // 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);
    

    我想我误解了你在回答中的问题。根据你的示例输入,你能说出你希望有符号整数的值是什么吗?你从来没有说过。输入:“6F D3 FD 45”.输出:大约-75.366465。我之所以说近似值,是因为我找到了一个点并呆在那里收集数据,同时用GPS测量了位置。因此上面的经度(-75.366465)应该接近,但可能不完全相同,与上面转换为有符号整数的十六进制字节的值相同(并执行了MAS到度的转换)。我试图找到一种方法,使用JavaMAS到度:除以3600000,从十六进制字节转换为有符号整数。接近…实际读数,去掉“负位”:“2F D3 FD 45”…将其与“10 2C 00 EA”的预期MAS值-75.366465进行比较…如果我翻转1到0和0到1(XOR),前22位匹配。我认为这可能是一个技巧-需要翻转所有位…我可以用XOR…@标记来实现这一点-你是对的。我很抱歉。看起来它可以实现这个技巧。但不确定
    &0x7FFFFFFF
    是否有必要。看起来&7fffffff和左/右移位做了同样的事情(删除最左边的顶部位)?我正在收集一些样本数据,以便进行测试this@Alison:不,这只是为了证明输入仅为较低的31位,而高位是无关的。第二行是我试图显示的,但Brad尚未确认这是否是所需的输出。@Brad:只是通过
    &7FFFFFFF
    wi进行andingI’我只需清除顶部的位。这会向左移动,但会以符号扩展的方式向右移动。换句话说,它会用第二位填充第一位。但我需要再次看到您想要的输出是什么…我不知道31个较低的位应该代表什么。为什么这个答案会被投票?它没有解决问题一点也不奇怪。请重新阅读这个问题!很抱歉出现了这样的问题。这个答案是否满足了您的要求?如果是的话,请随意接受。唯一的建议是,您可能会发现
    MAS=~MAS
    是切换MAS位的一种更清晰的方式。因此,考虑到这个解决方案,我假设输入的较低31位代表一个31位1的补码整数,你试图提取这个值?这就是你试图解决的问题吗?再次检查我的答案。我很确定我的原始答案是正确的。当我将我的转换应用于你的样本输入,然后除以3600000,我得到-75.369555,这是你的预期输出。当我进行转换时我得到的是-222,它不会摇摆。
    // 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);