9

Why does this code throw a NumberFormatException :

String binStr = "1000000000000000000000000000000000000000000000000000000000000000";
System.out.println(binStr.length());// =  64
System.out.println(Long.parseLong(binStr, 2));
A--C
  • 36,351
  • 10
  • 106
  • 92
Mickey Tin
  • 3,408
  • 10
  • 42
  • 71
  • 2
    Re-reading this, it's actually a good question. – Brian Roach Feb 17 '13 at 22:52
  • 1
    This may be an *interesting* question, but certainly not a [*good* question](http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist). – Jeroen Feb 18 '13 at 00:12

7 Answers7

7

1000000000000000000000000000000000000000000000000000000000000000 is larger than Long.MAX_VALUE.

See https://stackoverflow.com/a/8888969/597657

Consider using BigInteger(String val, int radix) instead.


EDIT:

OK, this is new for me. It appears that Integer.parseInt(binaryIntegerString, 2) and Long.parseLong(binaryLongString, 2) parse binary as sign-magnitude not as a 2's-complement.

Community
  • 1
  • 1
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • You missed what I missed when I first commented ;) It's not *larger* ... it doesn't exist. – Brian Roach Feb 17 '13 at 22:55
  • `String binStr = "1000000000000000000000000000000000000000000000000000000000000000"; System.out.println(binStr.length());// = 64 System.out.println(Long.parseLong(binStr, 2));` – Mickey Tin Feb 17 '13 at 22:58
  • 1
    That linked answer is wrong, Java represents integers as 2's-complement internally, not sign-magnitude. – Oliver Charlesworth Feb 17 '13 at 23:38
  • @OliCharlesworth You are right. But that's how `parseInt()` handles binary. – Eng.Fouad Feb 17 '13 at 23:41
  • @Eng.Fouad: Well, that's true in the sense that parseInt/parseLong expect negative numbers to be represented with a "-" character. But that's got nothing to do with the internal representation! – Oliver Charlesworth Feb 17 '13 at 23:46
5

Because it's out of range. 1000...000 is 263, but Long only goes up to 263 - 1.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • You missed what I missed when I first commented ;) It's not *larger*, it doesn't exist. – Brian Roach Feb 17 '13 at 22:53
  • So after all our discussion, it *should* be `Long.MIN_VALUE` from the bit pattern, but `parseLong` doesn't like that. Learn something new every day :) – Brian Roach Feb 18 '13 at 00:13
4

This is the same for all of Long, Integer, Short and Byte. I'll explain with a Byte example because it's readable:

System.out.println(Byte.MIN_VALUE); // -128
System.out.println(Byte.MAX_VALUE); // 127
String positive =  "1000000"; // 8 binary digits, +128 
String negative = "-1000000"; // 8 binary digits, -128
String plus     = "+1000000"; // 8 binary digits, +128
Byte.parseByte(positive, 2); //will fail because it's bigger than Byte.MAX_VALUE 
Byte.parseByte(negative, 2); //won't fail. It will return Byte.MIN_VALUE
Byte.parseByte(plus, 2);     //will fail because its bigger than Byte.MAX_VALUE

The digits are interpreted unsigned, no matter what radix is provided. If you want a negative value, you have to have the minus sign at the beginning of the String. JavaDoc says:

Parses the string argument as a signed long in the radix specified by the second argument. The characters in the string must all be digits of the specified radix (as determined by whether Character.digit(char, int) returns a nonnegative value), except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value or an ASCII plus sign '+' ('\u002B') to indicate a positive value. The resulting long value is returned.

In order to get MAX_VALUE we need:

String max  =  "1111111"; // 7 binary digits, +127 
// or
String max2 = "+1111111"; // 7 binary digits, +127 
jlordo
  • 37,490
  • 6
  • 58
  • 83
2

Largest long value is actually:

0111111111111111111111111111111111111111111111111111111111111111b = 9223372036854775807
SmRndGuy
  • 1,719
  • 5
  • 30
  • 49
2

This is because Long.parseLong cannot parse two's complement representation. The only way to parse two's complement binary string representation in Java SE is BigInteger:

long l = new BigInteger("1000000000000000000000000000000000000000000000000000000000000000", 2).longValue()

this gives expected -9223372036854775808result

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

This is the largest possible long (9223372036854775807 = 2 exp 63 - 1) in binary format. Note the L at the end of the last digit.

 long largestLong = 0B0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L;
Enrico Giurin
  • 2,183
  • 32
  • 30
-1

Actually, this is works for me:

String bitStr = "-1000000000000000000000000000000000000000000000000000000000000000";
System.out.println(Long.parseLong(bitStr, 2));

Here is a thing: inside Long.parseLong() code logic is looking for explicit sign first. And respectively to the sign, different limits are used (Long.MAX_VALUE for positive, and Long.MIN_VALUE for negative binary literals). Probably it would be better if this logic looked up first to the eldest bit (0 for positive and 1 for negative numbers) the sign