Converting 32-bit binary string with Integer.parseInt fails

前端 未结 4 728
慢半拍i
慢半拍i 2020-12-07 01:14

Why does this part of code fail:

Integer.parseInt(\"11000000000000000000000000000000\",2);

Exception in thread \"main\" java.lang.NumberFormatException: For         


        
相关标签:
4条回答
  • 2020-12-07 01:48

    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.

    0 讨论(0)
  • 2020-12-07 01:52

    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.

    0 讨论(0)
  • 2020-12-07 02:04

    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

    0 讨论(0)
  • 2020-12-07 02:08

    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.

    0 讨论(0)
提交回复
热议问题