[英]NumberFormatException while converting binary string to integer
我正在學習java中的位操作。 所以,我將二進制字符串轉換為整數字節和短。 這是我的程序:-
byte sByte,lByte; // 8 bit
short sShort,lShort; // 16 bit
int sInt,lInt; // 32 bit
sByte= (byte)(int)Integer.valueOf("10000000", 2); //Smallest Byte
lByte= (byte) ~sByte;
sShort= (short)(int)Integer.valueOf("1000000000000000", 2); //Smallest Short
lShort = (short) ~sShort;
sInt = (int) (int)Integer.valueOf("10000000000000000000000000000000", 2); //Smallest Int
lInt= (int)~sInt;
System.out.println("\"10000000\" \"8 bit\" byte=>"+sByte+"\t~byte=>"+lByte);
System.out.println("\"1000000000000000\" \"16 bit\" short=>"+sShort+"\t~short=>"+lShort);
System.out.println("\"10000000000000000000000000000000\" \"32 bit\" int=>"+sInt+"\t~int=>"+lInt);
Byte 和 Short 正在轉換並給出最小的 Byte 和最小的 Short Value,而 Integer 沒有得到轉換。
它拋出 NumberFormatException 如下:-
Exception in thread "main" java.lang.NumberFormatException: For input string: "10000000000000000000000000000000"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:583)
at java.lang.Integer.valueOf(Integer.java:740)
at com.learnjava.BitsManipulation.start(BitsManipulation.java:14)
at com.learnjava.learnjava.main(learnjava.java:9)
如果我評論那 3 個整數轉換行:-
// sInt = (int) (int)Integer.valueOf("10000000000000000000000000000000", 2); //Smallest Int
// lInt= (int)~sInt;
// System.out.println("\"10000000000000000000000000000000\" \"32 bit\" int=>"+sInt+"\t~int=>"+lInt);
它給了我輸出:-
"10000000" "8 bit" byte=>-128 ~byte=>127
"1000000000000000" "16 bit" short=>-32768 ~short=>32767
很好。我已經檢查了兩次字符串的長度,長度為 32,整數在 java 中是 32 位,這樣它應該可以工作,而這里不是這種情況。
如果我從 32 長度的字符串中刪除一個 0 或 1 或將 1 替換為 0,那么它也可以工作,如下所示:-
sInt = (int) (int)Integer.valueOf("00000000000000000000000000000000", 2); //Smallest Int
lInt= (int)~sInt;
System.out.println("\"00000000000000000000000000000000\" \"32 bit\" int=>"+sInt+"\t~int=>"+lInt);
sInt = (int) (int)Integer.valueOf("1000000000000000000000000000000", 2); //Smallest Int
lInt= (int)~sInt;
System.out.println("\"1000000000000000000000000000000\" \"31 bit\" int=>"+sInt+"\t~int=>"+lInt);
輸出如下: -
"00000000000000000000000000000000" "32 bit" int=>0 ~int=>-1
"1000000000000000000000000000000" "31 bit" int=>1073741824 ~int=>-1073741825
我對此感到困惑。 請告訴我它拋出 NumberFormatException 的原因以及此問題的解決方案。
簡短答案:
Integer.parseInt()方法(由Integer.valueOf()調用的方法)要求您告訴該數字是否為負數,因為它不是設計用來處理帶符號的數字。 通過添加減號“修復”您的代碼:
Integer sInt = Integer.valueOf("-10000000000000000000000000000000", 2);
System.out.println(sInt); // prints -2147483648
長答案:
您的stacktrace告訴您在哪里可以找到問題所在。 您的Integer.valueOf()方法調用Integer.parseInt(),后者又在第583行上引發NumberFormatException。您可以在openjdk中找到Integer類的代碼。
public static int parseInt(String s, int radix) throws NumberFormatException {
int result = 0;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
}
multmin = limit / radix;
while (i < len) {
digit = Character.digit(s.charAt(i++),radix);
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
為了清楚起見,我已經刪除了我們當前示例未運行的部分代碼。 請注意,限制為-2147483647(超過MIN_VALUE的一個)! 同樣,multmin為-1073741823。 在循環的第一次迭代中,結果為0,因此result * radix為0,數字為1(這是我們字符串中的第一個數字),因此結果-數字為-1。 在第二次迭代中,digit變為0,但是現在結果*基數為-2。 在第三次迭代中,我們得到-4,然后得到-8,依此類推...一直進行到結果等於-1073741824,這比我們的極限小一。
現在,我們還可以看到該方法檢查是否在數字上添加了符號(+或-)。 有趣的是,如果我們加上減號,我們會看到該限制設置為MIN_VALUE。 因此,違反直覺,我們可以通過添加減號來簡單地“修復”您的代碼:
Integer sInt = Integer.valueOf("-10000000000000000000000000000000", 2);
System.out.println(sInt); // prints -2147483648
另一方面,您在此處進行了一些奇怪的轉換。 代替:
sByte= (byte)(int)Integer.valueOf("10000000", 2);
您應該能夠寫:
sByte = Byte.valueOf("10000000", 2);
我說“應該”,因為實際上你做不到。 這導致另一個異常! 這是因為Byte.valueOf()方法只調用Integer.valueOf()方法,然后將答案轉換為Byte! 並且因為整數的10000000為000 ... 00010000000 = 128,它將告訴您對於一個字節來說太大了。
哇! 那么,為什么您怪異的鑄造技巧起作用了? 因為所謂的“無聲溢出”。 Java意識到您迫切希望將數字128容納在一個字節中,這是不可能的,因此它將盡可能多的數字放入其中(127),並通過添加其余的1環繞到底部,使您得到-128 。 我想這就是設計靜默溢出的目的,但是依賴它絕對不是一個好主意。 為了說明您的行中發生的情況:
sByte= (byte)(int)Integer.valueOf("10000000", 2);
Integer a = Integer.valueOf("10000000", 2);
System.out.println(a); // 128
int b = (int)a;
System.out.println(b); // 128
byte sByte = (byte)b;
System.out.println(sByte); // -128
因此,請勿在帶符號的數字上使用parseInt()或valueOf()。
在 kotlin 中像這樣轉換為 Long 然后 long 轉換為 Int
try {
val binaryString = "10010100101111111111000010100001"
if (binaryString.isEmpty()) println("number is empty")
else {
val number = binaryString.toLong(2)
println("number is ${number.toInt()}")
}
} catch (e: Exception) {
e.stackTrace.forEach {
kotlin.io.println("number is ${it.toString()}")
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.