代码之家  ›  专栏  ›  技术社区  ›  Brad Hein

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

  •  5
  • Brad Hein  · 技术社区  · 14 年前

    假设我从输入设备读取这些字节:“6F D4 06 40”。数字是以毫秒格式读取的经度。最高位(0x8000000)基本上始终为零,对于此问题将被忽略。

    我可以很容易地将字节转换为 未签名 整数:1876166208

    但是,如何将该无符号值转换为31位有符号整数的最终形式?

    到目前为止我只想到:

    1. 如果值&0x40000000,那么它实际上是负的,需要转换它
    2. 如果是负数,把上面的部分去掉,然后用剩下的部分做些什么。。。

    所以我可以判断它是否是一个负数,但是为了知道负数是什么值,我必须对剩余的部分做些什么-一个人的赞美?在Java中如何做到这一点?

    另一个问题是,如何在Java中将无符号整数转换为31位有符号整数?

    谢谢您!

    2 回复  |  直到 14 年前
        1
  •  4
  •   Mark Peters    14 年前

    答案取决于你输入的低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位表示2的补码整数,那么我认为您应该能够这样做:

    input = (input << 1) >> 1;
    

    这是因为Java在内部将整数存储在2的补码中:我们所做的就是向左移位,然后向右移位(有符号),这样符号位就被拾取,整数从31位变为32位。

    互补(期望输出:-802424384)

    补足

     1111 -> -7
     1110 -> -6
     ...
     1001 -> -1
     1000 -> -0 (anomoly)
     0000 ->  0
     0001 ->  1
    

    如果较低的31位代表 补足 整数(即符号位后跟表示无符号量值的30位),然后需要将其转换为2的补码,以便Java正确地提取值。要做到这一点,只需提取较低的30位并乘以-1:

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

    当我把-271317440除以3600000,得到-75.365955555556 ,所以我猜您的输入格式是2的补码,所以我的第一个和原始答案是正确的。

        2
  •  0
  •   Brad Hein    14 年前

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