1

I am loath to reinvent this bicycle and am hoping to be shown the tried and true way to handle this problem.

I'm collecting numeric values from users via some String interface (text input for instance).

I want to make sure that regardless of what type of memory space I'm using for collecting this info, I don't allow the user to enter a number that exceeds this value.

My intuition tells me that the only way to do this is to actually measure the string length of the max value... such as...

if( (userInput + "").length() > (Integer.MAX_VALUE + "").length()){
   //user has entered too many digits for an Integer to hold.
}

But this looks ugly to me and I'm guessing there's a cleaner way to handle this.

Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236
  • 1
    Have you see this related question: http://stackoverflow.com/questions/8391979/does-java-have-a-int-tryparse-that-doesnt-throw-an-exception-for-bad-data – J. Schmale Jan 13 '17 at 20:42
  • This wouldn't handle `userInput` being 2147483648, where `Interger.MAX_VALUE = 2147483647`. – imtheman Jan 13 '17 at 20:43
  • 1
    @imtheman - precisely - I was saying this approach is inadequate - you're adding to the reasons why that is so - it's entirely my intention to not do it this way :) – Yevgeny Simkin Jan 13 '17 at 20:44

3 Answers3

1

When you get the userInput for the first time you should verify that what the user enters is valid and if it is, then Integer.parseInt() will work. If it's not valid, i.e. a value greater than Integer.MAX_VALUE, it will throw an exception.

The behavior you're describing leads to using the catch as flow control which is not a good design...

BAD:

try{
    Integer.parseInt(max);
    //do something with the integer
}catch (NumberFormatException e)
{
    //user has entered too many digits for an Integer to hold.
    userInput = Integer.MAX_VALUE + "";
}
RAZ_Muh_Taz
  • 4,059
  • 1
  • 13
  • 26
1

The constructor of Integer would detect that for you, by throwing a NumberFormatException if the user input is either out of range or not really an integer. See the following test program example:

public class UserInputBigInteger {

    public static void main(String[] args) {
        String[] inputStrings = {
                String.valueOf(Integer.MAX_VALUE)
                , String.valueOf(Integer.MAX_VALUE)+"0" // x10
                , String.valueOf(Integer.MAX_VALUE)+"a" // not an integer
        };

        for (String inputString : inputStrings) {
            try {
                Integer inputInteger = new Integer(inputString);
                final int MAX = Integer.MAX_VALUE;
                System.out.format("userInput %s is within range %,d%n"
                        , inputString, MAX);
            } catch (NumberFormatException ex) {
                System.out.format("userInput does not appear to be valid interger: %s%n"
                        , ex.getMessage());     }
        }
    }

}

The output would be:

userInput 2147483647 is within range 2,147,483,647
userInput does not appear to be an interger: For input string: "21474836470"
userInput does not appear to be an interger: For input string: "2147483647a"
leeyuiwah
  • 6,562
  • 8
  • 41
  • 71
-1

You could also try this to get the bit information:

BigInteger userInputCheck=new BigInteger(userInput);

if(userInputCheck.bitLength()>31){
      //error : cannot convert the input to primitive int type
}

EDIT

If you are using Apache Commons there is a method createNumber# in the NumberUtils utility class.

From the documentation:

    ...it starts trying to create successively larger types from the type specified 
until one is found that can represent the value...

Source Code for the above method

boxed__l
  • 1,334
  • 1
  • 10
  • 24
  • The constructor of the integer type (`Integer` or `Long`) would do the range check for you. (See my answer above). Also, the code should try not be tied to a physical characteristic (number of bits 32). They key is whether or not the input string can be represented as a number (not how many bits are there in the representation). – leeyuiwah Jan 13 '17 at 22:03
  • 1
    @leeyuiwah Agreed. in the Open JDK version of the Integer class the checks are done by the static `parseInt()` method so you can directly call it. Since the JVM guarantees the bit representations of the primitive types across platforms I think the solution is safe (for now). But yes since the wrapper classes themselves perform this check it is recommended to go with it. My solution is just another way of tackling the problem... – boxed__l Jan 13 '17 at 22:21