Reputation: 11
we have byte string s = "1111000000000111000000000001000000000010010000000000000000000000"
(this value equal -1150951111012646912), if we use Long.parseLong(s, 2)
, we got "
java.lang.NumberFormatException: For input string: "1100000001000000010000000100000000001110000000010000010000000000" under radix 2".
i fixed this problem with this way to convert
new BigInteger(s, 2).longValue();
Explain please i can't understand what happend?
Same situation with this value:
s = 1100000001000000010000000100000000001110000000010000010000000000
(equal -4593600976060873728)
new BigInteger(s, 2).longValue();
Upvotes: 1
Views: 680
Reputation: 40034
The short answer is that neither Integer.parseInt
nor Long.parseLong
can parse twos complement negative numbers without replacing the sign bit with an explicit '+'
or '-'
sign.
This is probably in keeping with parsing a decimal number such as the following:
String max = "9223372036854775807"; // Long.MAX_VALUE
String maxPlus1 = "9223372036854775808"; // Long.MAX_VALUE+1
long m = Long.parseLong(max,10); //OK
long m1 =Long.parseLong(maxPlus1,10)); // throws exception
To parse your two's complement value of long or any other value you can use
Long.parseUnsignedLong. All the following three method calls correctly parse the values, printing out Long.MIN_VALUE
, the fourth one being your specific value in your question.
System.out.println(Long.parseUnsignedLong("1000000000000000000000000000000000000000000000000000000000000000",2));
System.out.println(Long.parseUnsignedLong("8000000000000000",16));
System.out.println(Long.parseUnsignedLong("9223372036854775808",10));
System.out.println(Long.parseUnsignedLong("1111000000000111000000000001000000000010010000000000000000000000",2));
prints
-9223372036854775808
-9223372036854775808
-9223372036854775808
-1150951111012646912
Upvotes: 3
Reputation: 48600
You are trying to parse a 64-bit unsigned (long) integer as a 64-bit signed (long) integer.
Java's long
is not unsigned. You will only be able to store a positive number up to 63 bits. The max value for a long
is 9,223,372,036,854,775,807
or 2^(63)
.
The most-significant bit (left-most) is the signed bit.
Note: Any leading zeroes will not be displayed.
import java.math.BigInteger;
public class NumberUtils {
static final String MIN_SIGNED_LONG_BINARY = Long.toBinaryString(Long.MIN_VALUE);
static final String MAX_SIGNED_LONG_BINARY =
padStart(Long.toBinaryString(Long.MAX_VALUE), 64, "0");
public static void main(String[] args) {
parseBinary("1111000000000111000000000001000000000010010000000000000000000000");
parseBinary("1100000001000000010000000100000000001110000000010000010000000000");
}
private static void parseBinary(String str) {
BigInteger bigInt = new BigInteger(str, 2);
System.out.println(bigInt.longValue());
try {
Long.parseLong(str, 2);
} catch (NumberFormatException e) {
System.out.printf(
"Error:%n* Min: %s (%d bits)%n* Val: %s (%d bits)%n* Max: %s (%d bits)%n",
MIN_SIGNED_LONG_BINARY,
MIN_SIGNED_LONG_BINARY.length(),
str,
str.length(),
MAX_SIGNED_LONG_BINARY,
MAX_SIGNED_LONG_BINARY.length());
}
}
public static String padStart(String inputString, int targetLength, String padString) {
if (inputString.length() >= targetLength) return inputString;
StringBuilder sb = new StringBuilder();
while (sb.length() < targetLength - inputString.length()) {
sb.append(padString);
}
return sb.append(inputString).toString();
}
}
-1150951111012646912
Error:
* Min: 1000000000000000000000000000000000000000000000000000000000000000 (64 bits)
* Val: 1111000000000111000000000001000000000010010000000000000000000000 (64 bits)
* Max: 0111111111111111111111111111111111111111111111111111111111111111 (64 bits)
-4593600976060873728
Error:
* Min: 1000000000000000000000000000000000000000000000000000000000000000 (64 bits)
* Val: 1100000001000000010000000100000000001110000000010000010000000000 (64 bits)
* Max: 0111111111111111111111111111111111111111111111111111111111111111 (64 bits)
Upvotes: 0
Reputation:
You're passing in a size 64 binary string, which is bigger than the signed byte size of a long. Since parseLong
doesn't accept unsigned binary representations and instead wants a - or (an optional) + in front of the number to denote the sign, it throws an error. The max byte length you can pass into parseLong is 63.
An equivalent parseLong
call to your first example would be Long.parseLong("-111111111000111111111110111111111101110000000000000000000000", 2)
, using the - sign and the two's complement of the number.
Upvotes: 1