2

I'm just wondering why my code is giving me a NumberFormatException?

From other posts on stack overflow people seem to be having trouble with whitespace, except mine doesn't seem to have this issue at all.

package suop.space;

import java.util.BitSet;

public class ColourUtils {
    public static short getAlpha(final int rgb) {
        return (short) ((rgb >> 24) & 0xff);
    }

    public static short getRed(final int rgb) {
        return (short) ((rgb & 0x00ff0000) >> 16);
    }

    public static short getGreen(final int rgb) {
        return (short) ((rgb & 0x0000ff00) >> 8);
    }

    public static short getBlue(final int rgb) {
        return (short) (rgb & 0x000000ff);
    }

    public static int getRGB(int alpha, int red, int green, int blue) {

        BitSet rgbValueBitSet = new BitSet(32);

        addIntToBitSet(alpha, rgbValueBitSet, 0);
        addIntToBitSet(red, rgbValueBitSet, 9);
        addIntToBitSet(green, rgbValueBitSet, 17);
        addIntToBitSet(blue, rgbValueBitSet, 25);


        System.out.println("rgbValueBitSet: " + rgbValueBitSet);

        StringBuilder rgbBinaryStringBuilder = new StringBuilder();
        for (int i = 0; i < rgbValueBitSet.length(); i++) {
            if (rgbValueBitSet.get(i)) {
                rgbBinaryStringBuilder.append(1);
            } else {
                rgbBinaryStringBuilder.append(0);
            }
        }

        System.out.println(rgbBinaryStringBuilder.toString());

        int rgbValue = Integer.parseInt(rgbBinaryStringBuilder.toString(), 2);
        System.out.println(rgbValue);

        return rgbValue;
    }

    private static void addIntToBitSet(int inputInt, BitSet inputBitSet, int byteToStartFrom) {

        char[] inputCharArray = Integer.toBinaryString(inputInt).toCharArray();
        int[] inputIntArray = new int[inputCharArray.length];

        for (int i = 0; i < inputCharArray.length; i++) {
            inputIntArray[i] = Character.getNumericValue(inputCharArray[i]);
        }

        for (int i = 0; i < inputIntArray.length; i++) {
            if (inputIntArray[i] >= 1) {
                inputBitSet.set(i + byteToStartFrom);
            } else {
                inputBitSet.clear(i + byteToStartFrom);
            }
        }
    }
}

When trying to run the program I get this error:

rgbValueBitSet: {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 17, 18, 20, 21, 22, 23, 25, 26, 28, 29, 30, 31}
11111111011011110110111101101111
Exception in thread "main" java.lang.NumberFormatException: For input string: "11111111011011110110111101101111" under radix 2
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:660)
    at suop.space.ColourUtils.getRGB(ColourUtils.java:45)
    at suop.space.EffectsUtils.divideByTwo(EffectsUtils.java:19)
    at suop.space.Main.main(Main.java:38)

Process finished with exit code 1

That 11111111011011110110111101101111 is what I'm trying to parse through Integer.parseInt().

I'm guessing that maybe it's trying to make 11111111011011110110111101101111 itself an int, which is way larger than an integer can be. The thing is that telling it the radix I thought would make it identify it as binary, although I'm not certain.

6
  • The maximum value of an integer is 2147483647, 11111111011011110110111101101111 in decimal is 4285493103, which is way larger. Are you by any chance not trying to actually parse a binary number and instead trying to define an integer by setting the bits? Commented Jul 14, 2021 at 12:27
  • Seems like you've answered your own question if the value can't be represented as an int. Commented Jul 14, 2021 at 12:29
  • @OHGODSPIDERS What would the difference be? Commented Jul 14, 2021 at 12:31
  • The maximum value of an integer is 2147483647, 11111111011011110110111101101111 in decimal is 4285493103, which is way larger. Are you by any chance not trying to actually parse a binary number and instead trying to define an integer by setting the bits? – OH GOD SPIDERS Yeah, that's what I was trying to do. It might be a fundamental mistake on my part but ImageIO's getRGB() returns an integer, with 8 bits for alpha, 8 for red etc. As an actual integer it reads generally as something like -9474193, and I'm trying to return something like that. Commented Jul 14, 2021 at 12:36
  • 1
    If you want to 'getRGB' from its components, wouldn't you just do a bitwise recomposition of those components? Commented Jul 14, 2021 at 12:41

1 Answer 1

5

You have a string representing a 32-bit unsigned value. An 'int' is a 32-bit signed value, i.e., absent a sign in the string value, the input cannot require more than 31 bits.

That the internal representation of a negative number has the high bit set does not mean that you can explicitly set the high bit in the string representation of that number.

You're in the same situation you'd be in by trying

  parseInt("4285493103", 10);

In Java 8 onwards, there is parseUnsignedInt, which looks to me like it does what you want. I can't personally vouch for that, having never needed to use it.

Otherwise, use parseLong.

by telling it the radix I thought would make it identify it as binary,

It's being parsed as binary: which means only that it is base 2. The radix changes nothing about the representation of negative values and nor does it change the absolute range allowed.


Maybe this little test program will help you to see what is going on?

class N {
    static public void main(String... a) {
        System.out.println(Integer.parseUnsignedInt("11111111011011110110111101101111", 2));
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

excerpt from my previous comment - "It might be a fundamental mistake on my part but ImageIO's getRGB() returns an integer, with 8 bits for alpha, 8 for red etc. As an actual integer it reads generally as something like -9474193, and I'm trying to return something like that." Instead of trying to get 4285493103, I'm trying to get -9474193, which is 11111111 01101111 01101111 01101111 encoded into a 32 bit signed integer, which is what java uses (to my knowledge). What would I do instead?
Use parseUnsignedInt. 4285493103 and -9474193 are the same number in internal representation. If you parse it as unsigned, and then print it as an 'int', you'll see that to be the case.
Try running the little example program I posted.
Oh. Cheers! Thanks for the help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.