簡體   English   中英

Java-將int轉換為字節數組而不考慮符號

[英]Java - converting int to byte array without considering sign

要將int轉換為字節數組,我使用以下代碼:

int a = 128;
byte[] b = convertIntValueToByteArray(a);
private static byte[] convertIntValueToByteArray(int intValue){
  BigInteger bigInteger = BigInteger.valueOf(intValue);
  byte[] origByteArray = bigInteger.toByteArray();
  byte[] noSignByteArray = new byte[bigInteger.bitLength()/8];

  if(bigInteger.bitLength()%8!=0){
    noSignByteArray = origByteArray;
  }else{
    System.arraycopy(origByteArray,1,noSignByteArray,0,noSignByteArray.length);
  }

  return noSignByteArray;
}

我正在嘗試做兩件事。

1)我需要知道原始整數的字節數(四舍五入為關閉字節)。 但是,當我調用toByteArray()方法時,不需要為符號位添加的其他位。 這就是為什么我有輔助方法的原因。 因此,在此示例中,如果沒有輔助方法,則當我將128轉換為字節數組時,由於符號位的原因,長度為2個八位位組,但我只是期望它是一個八位位組。

2)我需要數字的正表示。 在此示例中,如果嘗試打印數組b中的第一個元素,則得到-128。 但是,我將要使用的數字只能是正數,因此我真正想要的是128。我僅限於使用字節數組。 有沒有辦法做到這一點?

更新的帖子

感謝您的回復。 我沒有找到我想要的確切答案,因此我將嘗試提供更多詳細信息。 最終,我想在數據輸出流上寫入不同類型的值。 在本文中,我想說明將int寫入數據輸出流時會發生什么。 我遇到了兩種情況。

1)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());

byte[] b = BigInteger.valueOf(128).toByteArray();

os.write(b);

2)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
os.write(128);

在第一種情況下,當從數據輸入流中讀取字節時,似乎字節數組中的第一個元素為0表示msb,而數組中的第二個元素包含數字-128。 但是,由於msb為0,我們將能夠確定它打算為正數。 在第二種情況下,沒有msb,並且從輸入流讀取的字節數組中存在的唯一元素是-128。 我期望數據輸出流的write()方法以與toByteArray()方法對BigInteger對象相同的方式將int轉換為字節數組。 但是,由於不存在msb,因此似乎並非如此。 所以我的問題是,在第二種情況下,我們應該如何知道如果沒有msb,則128應該是一個正數,而不是一個負數。

您可能已經知道

  • 在一個八位位組中,根據外部解釋,模式10000000可以解釋為128或-128
  • Java的byte類型僅將八位byte解釋為-128 ... 127中的值。

如果您要構建一個應用程序,其中整個世界僅由非負整數組成,那么您可以在字節值-128表示128和-127表示129和...以及-的前提下簡單地完成所有工作。 1表示255。這當然是可行的,但需要花一些工夫。

像這樣處理“無符號字節”的概念通常是通過將字節擴展為全都設置為零的shortint的高階位,然后執行算術或顯示值來完成的。 您將需要確定這種方法是否更符合您的喜好,而不只是在數組中將128表示為兩個八位位組。

我認為以下代碼可能就足夠了。

在java中, int是二進制補碼二進制數:

-1              = 111...111
ones complement = 000...000; + 1 =
1               = 000...001

所以關於標志位我不明白。 就是這樣,您可以執行Math.abs(n) 字節的范圍是-128到127,但是解釋是屏蔽問題,如下所示。

public static void main(String[] args) {
    int n = 128;

    byte[] bytes = intToFlexBytes(n);
    for (byte b: bytes)
        System.out.println("byte " + (((int)b) & 0xFF));
}

public static byte[] intToFlexBytes(int n) {
    // Convert int to byte[4], via a ByteBuffer:
    byte[] bytes = new byte[4];
    ByteBuffer bb = ByteBuffer.allocateDirect(4);
    bb.asIntBuffer().put(n);
    bb.position(0);
    bb.get(bytes);

    // Leading bytes with 0:
    int i = 0;
    while (i < 4 && bytes[i] == 0)
        ++i;

    // Shorten bytes array if needed:
    if (i != 0) {
        byte[] shortenedBytes = new byte[4 - i];
        for (int j = i; j < 4; ++j) {
            shortenedBytes[j - i] = bytes[j]; // System.arrayCopy not needed.
        }
        bytes = shortenedBytes;
    }
    return bytes;
}

要回答您的第一個問題(使用無符號表示來表示非負整數需要多少字節),請考慮以下我在Common Lisp中編寫的函數。

(defconstant +bits-per-byte+ 8)

(defun bit-length (n)
  (check-type n (integer 0) "a nonnegative integer")
  (if (zerop n)
      1
      (1+ (floor (log n 2)))))

(defun bytes-for-bits (n)
  (check-type n (integer 1) "a positive integer")
  (values (ceiling n +bits-per-byte+)))

這些突出顯示了問題的數學基礎:即,對告訴您,控制給定的非負整數(被調整為帶有floor的階躍函數)需要多少次冪(由位提供),並調整了它的字節數需要再次保持該位數作為步進函數,這次用ceiling調整。

請注意,數字零不能作為對數函數的輸入,因此我們明確避免使用它。 您可能會注意到,也可以通過對核心表達式進行一點轉換來編寫bit-length函數:

(defun bit-length-alt (n)
  (check-type n (integer 0) "a nonnegative integer")
  (values (ceiling (log (1+ n) 2))))

不幸的是,作為一個對數始終為零 ,不管是基礎的,這個版本說,整零可以通過零位表示,這不是我們想要的答案。

對於第二個目標,您可以使用上面定義的函數來分配所需的字節數,並遞增設置所需的位,而忽略符號。 很難說出在字節向量中設置正確的位是否遇到麻煩,或者您的問題是在解釋位時避免將高位視為符號位(即二進制補碼表示 )。 請詳細說明您需要什么樣的推動才能使自己再次前進。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM