Integer.valueOf(String, int radix)
and Integer.parseInt(String, int radix)
將只解析值爲-2 147 483 648至2 147 483 647的數字,即32位有符號整數的值。
這些函數不能解釋binary的二進制補碼(radix = 2
),因爲傳遞的字符串可以是任意長度,所以前導1可以是數字或符號位的一部分。我猜Java開發人員決定繼續進行的最合理的方法是永遠不要接受二進制補碼,而不是假設第32位是符號位。
他們讀取您的輸入二進制字符串爲無符號3 549 763 730(大於最大int值)。要讀取負值,您需要在前面輸入-
的正數。例如,對於-5
:
Integer.parseInt("1011", 2); // 11
// Even if you extended the 1s to try and make two's complement of 5,
// it would always read it as a positive binary value
Integer.parseInt("-101", 2); // -5, this is right
解決方案:
我建議,第一,如果你可以將它存儲與你自己(如-
符號)額外的符號信息的正數,做到這一點。例如:
String binString;
if(i < 0)
binString = "-" + Integer.toBinaryString(-i);
else // positive i
binString = Integer.toBinaryString(i);
如果您需要使用符號二進制字符串,以便採取以二進制補碼形式的負數(作爲一個字符串),並將其解析爲int,我建議你把補手動將其轉換爲int,然後更正該符號。回想一下,2的補碼= 1的補碼+1,而1的補碼只是反轉每一位。
作爲一個實現實例:
String binString = "11010011100101010001100010010010";
StringBuilder onesComplementBuilder = new StringBuilder();
for(char bit : binString.toCharArray()) {
// if bit is '0', append a 1. if bit is '1', append a 0.
onesComplementBuilder.append((bit == '0') ? 1 : 0);
}
String onesComplement = onesComplementBuilder.toString();
System.out.println(onesComplement); // should be the NOT of binString
int converted = Integer.valueOf(onesComplement, 2);
// two's complement = one's complement + 1. This is the positive value
// of our original binary string, so make it negative again.
int value = -(converted + 1);
你也可以寫你自己的32位二進制補碼數的版本Integer.parseInt
。當然,這是假設你沒有使用Java 8,並且不能僅僅使用Integer.parseUnsignedInt
,@llogiq在我輸入時指出了這一點。
編輯:您還可以使用Long.parseLong(String, 2)
第一,然後計算補(和0xFFFFFFFF的面膜吧),那麼降級long
到int
。更快寫入,可能更快的代碼。
請注意,一個簡短的方式來獲得一個有符號補數n的負等價物只是做〜n + 1 – fge
我試圖繞過'Integer.valueOf'不解釋32位二進制補碼二進制字符串 - 所以我基本上做了'〜n'作爲一個字符串,並在解釋它之後做了'+ 1'。然而,在我寫了這個解決方案後,我意識到可以做'Long.parseLong(String,2)',以數字的形式進行二進制補碼運算,然後將其重新轉換爲int。 – Laogeodritt
謝謝!總之,處理負數和基數是兩個時非常不直觀。但作爲一般API,它只能是這樣。 – zhuguowei