簡體   English   中英

BigInteger,BitSet及其位和字節順序

[英]BigInteger, BitSet and their bit and byte order

考慮以下代碼(java8):

@Test
public void testBigIntegerVsBitSet() throws Throwable
{
    String bitString529 = "00000010 00010001";        // <- value = 529 (LittleEndian)
    byte[] arr529 = new byte[] { 0x02, 0x11 };        // <- the same as byte array (LittleEndian)
    BigInteger bigIntByString = new BigInteger( bitString529.replace( " ", ""), 2); // throws if there is a blank!
    BigInteger bigIntByArr = new BigInteger( arr529);
    BitSet bitsetByArr = BitSet.valueOf( arr529);  // interpretes bit-order as LittleEndian, but byte-order as BigEndian !!!

    System.out.println( "bitString529     : " + bitString529);              // bitString529     : 00000010 00010001
    System.out.println( "arr529.toString  : " + Arrays.toString( arr529));  // arr529.toString  : [2, 17]
    System.out.println( "bigIntByString   : " + bigIntByString);            // bigIntByString   : 529
    System.out.println( "bigIntByArr      : " + bigIntByArr);               // bigIntByArr      : 529
    System.out.println( "bitsetByArr      : " + bitsetByArr.toString() );   // bitsetByArr      : {1, 8, 12}
    System.out.println( "expecting        : {0, 4, 9}");                    // expecting        : {0, 4, 9}

    String bigIntByStringStr = toBitString( bigIntByString::testBit);
    String bigIntByArrStr = toBitString( bigIntByArr::testBit);
    String bitsetByArrStr = toBitString( bitsetByArr::get);

    System.out.println( "bigIntByStringStr: " + bigIntByStringStr);         // bigIntByStringStr: 1000100001000000
    System.out.println( "bigIntByArrStr   : " + bigIntByArrStr);            // bigIntByArrStr   : 1000100001000000
    System.out.println( "bitsetByArrStr   : " + bitsetByArrStr );           // bitsetByArrStr   : 0100000010001000
}

private String toBitString( Function<Integer, Boolean> aBitTester)
{
    StringBuilder sb =  new StringBuilder();
    for ( int i = 0; i < 16; i++ )
    {
        sb.append( aBitTester.apply( i) ? "1" : "0");
    }
    return sb.toString();
}

這證明BitSet將字節數組解析為BIG_ENDIAN,而將(單個字節的)位順序解釋為LITTLE_ENDIAN。 相反,即使是由位字符串加載,BigInteger也會以LITTLE_ENDIAN進行解釋。

特別是對兩個類的位索引(BitInteger :: testBit與BitSet :: get)的迭代提供了不同的結果。

是否存在這種不一致的原因?

字節序大多僅指字節的順序,而不是指各個位的順序。 后者與大多數應用程序無關,因為例如您不能尋址內存中的各個位。 因此,字節中的位的字節序僅在重要的情況下使用,例如串行數據總線,否則,字節通常被視為它們所代表的數字而沒有任何字節序(請參閱Wikipedia ,關於“ 可以字節序”的答案是指位)以字節為單位? )。

因此,由於此BitSet將字節視為其最低有效位,因此當您將字節賦予0x01 ,無論字節排序使用何種字節序,都將獲得最低位的​​預期結果。 這就是為什么使用BigIntegerBitSet輸出僅在字節順序上有所不同的原因。

請注意,對於字節順序, BitSet使用小字節序,而BigInteger使用大字節序(與您聲明的內容不同)。

至於BitSet為什么使用與BigInteger不同的字節序,我們只能推測。 請注意,受人尊敬的BitSet方法更新得多(僅在Java 1.7中引入),因此自BigInteger引入以來,小字節序和大字節序的重要性可能已經改變。

暫無
暫無

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

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