14

Why does this part of code fail:

Integer.parseInt("11000000000000000000000000000000",2);

Exception in thread "main" java.lang.NumberFormatException: For input string: "11000000000000000000000000000000"

As far as I understand Integer is a 32 bit value. The number of zeros and ones in the upper code is 32. If there are 31 the code works. Why is that so?

wrschneider
  • 17,913
  • 16
  • 96
  • 176
Aliens
  • 984
  • 3
  • 14
  • 23
  • The accepted answer here is not correct. The same question with correct answers can be found here: [Java, Long.parse binary String](http://stackoverflow.com/questions/14926920/java-long-parse-binary-string/14927505#14926948) – jlordo Feb 18 '13 at 00:14

4 Answers4

18

Your code fails because it tries to parse a number that would require 33 bits to store as a signed integer.

A signed int is a 32 bit value in two's complement representation, where the first bit will indicate the sign of the number, and the remaining 31 bits the value of the number. (-ish.) Java only supports signed integers, and parseInt() and friends aren't supposed to parse two's complement bit patterns – and thus interpret the 1 or (possibly implied) 0 at the 32nd position from the right as the sign. They're meant to support parsing a human-readable reprentation, which is an optional - (or +) for the sign, followed by the absolute value of a number.

In this context, it's a false intuition that leads you to expect the behaviour you describe: if you were parsing any other base besides base 2 (or maybe the other commonly used power-of-two bases), would you expect the first digit of the input to affect the sign? Obviously you wouldn't; having, say, parseInt("2147483648") return -2147483648 by design would be PHP levels of crazy.

Special-casing power-of-two bases also feels odd. Better to have a separate approach to handling bit patterns, for example the one in this answer.

Community
  • 1
  • 1
millimoose
  • 39,073
  • 9
  • 82
  • 134
  • I just reread the javadocs for Integer.parseInt() yet again, and I do not see anything saying "this doesn't parse negative numbers" (in fact, it says "signed int"), or, at least explicitly, "this doesn't parse bit patterns". In fact, as described in the javadocs, one could argue that a String of 55 0s should parse to 0. I consider the behavior a bug. But doesn't look like Oracle or OpenJDK will fix it. Do you see anything in the javadocs to contradict this? – user949300 Jan 17 '12 at 02:55
  • @user949300 `parseInt` will parse negative binary numbers, if you pass them in as, say, "-10010110". It will also parse a string of 55 zeroes, because it's a valid value for an `int`. A 32-bit number without leading zeroes is not a valid `int` value, and so it's rejected. – millimoose Jan 17 '12 at 15:15
  • @user949300 What I meant by "won't parse bit patterns" is that what `Integer.parseInt(str, 2)" parses is a number written in base 2. It does not parse a stringified two's complement binary representation of a 32-bit integer. I don't consider this a bug, I just consider it something the method is not intended for – which is parsing "human" textual representations of numbers in arbitrary bases. – millimoose Jan 17 '12 at 15:21
  • @Interdial Hmm, I didn't think 55 zeros worked. Thanks for testing! I think it's strange that 55 0s works and 32 1s don't, but that's the way it is. – user949300 Jan 17 '12 at 17:41
  • 2
    Java represents integers in **2's-complement**, not sign-magnitude. – Oliver Charlesworth Feb 17 '13 at 23:37
  • To support what Oli Charlesworth just said, have a look at this question: [Java, Long.parse binary String](http://stackoverflow.com/questions/14926920/java-long-parse-binary-string/14927505#14926948) – jlordo Feb 18 '13 at 00:13
  • @OliCharlesworth Right, I rephrased the answer. – millimoose Feb 18 '13 at 10:32
  • @jlordo Supporting his comment by another comment of his saying this very answer is wrong, just elsewhere? I thought that only works in liberal arts and punditry ;) – millimoose Feb 18 '13 at 10:38
  • @millimoose: Yesterday's question brought us here, and after I saw Oli comment, I thought it would be fair to link to the new question. Wasn't meant as an offence, and my -1 is now a +1 ;) – jlordo Feb 18 '13 at 10:42
4

According to the docs, the max value of an Integer is 2^31-1. Which, in binary is:

1111111111111111111111111111111

In other words, 31 1's in a row.

Akos K
  • 7,071
  • 3
  • 33
  • 46
Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
2

This is because for Integer.parseInt "11000000000000000000000000000000" is not a two's complement representation of -1073741824 but a positive value 3221225472 which does not fit into int values range -2147483648 to 2147483647. But we can parse two's complement binary string representation with BigInteger:

int i = new BigInteger("11000000000000000000000000000000", 2).intValue()

this gives expected -1073741824 result

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

Even though your string, "11.....lots of zeros" is a legal binary representation of a negative integer, Integer.parseInt() fails on it. I consider this a bug.

Adding a little levity, since on rereading this post it sounds too pedantic, I understand that Oracle probably doesn't care much whether I think this is a bug or not. :-)

You can try:

   long avoidOverflows = Long.parseLong("11000000000000000000000000000000",2);
   int thisShouldBeANegativeNumber = (int)avoidOverflows);
   System.out.println(avoidOverflows + " -> " + thisShouldBeANegativeNumber);

you should see
3221225472 -> -1073741824

You sometimes have to do this with Colors depending on how they are stored as text.

BTW, exact thing can happen if you are parsing a Hex representation and you are parsing a negative number like "88888888". You need to use Long.parseLong() then convert.

user949300
  • 15,364
  • 7
  • 35
  • 66
  • It's not a bug. JavaDoc states, that if you want a negative Integer from `parseInt()`, you have to have an ASCII minus `-` at the beginning of the String. Have look at this question: [Java, Long.parse binary String](http://stackoverflow.com/questions/14926920/java-long-parse-binary-string/14927505#14927505) – jlordo Feb 18 '13 at 00:21