1

I wrote Java code to convert String to long. However, when dealing with overflow problem, I don't have clues how to solve it. If a number is overflowed, computer believe every number is legal in storage. How to let program, with 64bit jdk ,detect the real number is overflowed is the key problem. And I'm not allowed to use any built-in library such as parseLong or others.

public static long strTolong(String s){
        //error checking
        if(s == null) return 0;
        s = s.trim();//remove all space character
        boolean neg = false;//judge the number is negative or positive
        int pos = 0 ; //index of string
        long result = 0;
        //check positive or negative
        if(s.charAt(pos) == '-'){
            neg = true;
            pos++;
        }else if(s.charAt(pos) == '+') pos++;

        //calculate result
        while(pos<s.length()){
            if(s.charAt(pos) >='0' && s.charAt(pos) <='9'){
                result = result*10+(s.charAt(pos) - '0');
            }else
                break;
            pos++;
        }
        if(neg) result =-result;

        //check overflow
        if(result >Long.MAX_VALUE) {
            return Long.MAX_VALUE;
        }
        if(result<Long.MIN_VALUE){
            return Long.MIN_VALUE;
        }


        return result;
    }

If data is larger than long.maxvalue, the result can't be stored in computer correctly.

How to solve this problem?

Chris Su
  • 543
  • 8
  • 16

3 Answers3

1

Your best option is probably to do a lexicographical comparison between the input and the minimum/maximum numbers before you start.

static int compare(String v1, String v2) {
    boolean neg1 = v1.startsWith("-");
    boolean neg2 = v2.startsWith("-");
    return neg1 ? (neg2 ? -comparePositives(v1.substring(1),v2.substring(1)):-1)
                : (neg2 ? 1 : comparePositives(v1, v2));
}

static int comparePositives(String v1, String v2) {
    // Is one longer?
    if (v1.length() != v2.length())
        return v1.length() < v2.length() ? -1 : 1;

    // Both empty?
    if (v1.isEmpty())
        return 0;

    // First digit differs?
    if (v1.charAt(0) != v2.charAt(0))
        return v1.charAt(0) < v2.charAt(0) ? -1 : 1;

    // Recurse on rest of number
    return comparePositives(v1.substring(1), v2.substring(1));
}

Use it for instance as follows:

if (compare(s, ""+Long.MIN_VALUE) == -1)
    throw new NumberFormatException("Input too small");

if (compare(s, ""+Long.MAX_VALUE) == 1)
    throw new NumberFormatException("Input too large");

Tested here: http://ideone.com/HmMkJ3

Note that the code does not check that the input is well formed. I suggest you do such check first. (Be aware of cases like 0 and -0 etc.)

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • Your solution is impressive. However, the built-in library is used here. And the regular expression way is so as well. – Chris Su Sep 24 '14 at 20:37
  • The key problem is computer wouldn't notice the data is overflowed. – Chris Su Sep 24 '14 at 20:38
  • http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-fo This solution does the same thing as well. – Chris Su Sep 26 '14 at 21:02
0

You could do the same thing that Long#parseLong would do:

 throw new NumberFormatException("too long (pun intended): "+s);
Thilo
  • 257,207
  • 101
  • 511
  • 656
0

I am not sure what you trying to achieve here. If String is greater than Long.MAX_VALUE means that is no more a Long value.

If your String value is withing the range of Long, you can use Long.parseLong() with out this kind of hard ways.

If you want to have huge number you can use BigDecimal easily

String max = Long.MAX_VALUE+"";
System.out.println(max);
long maxL=Long.parseLong(max)+1;
System.out.println(maxL);
BigDecimal bigDecimal=new BigDecimal(max).add(new BigDecimal("1"));
System.out.println(bigDecimal); 

Out put:

9223372036854775807 // long max value
-9223372036854775808 // incorrect result in long
9223372036854775808 // BigDecimal gives you correct one

For your case you can throws an Exception if value is greater than Long.MAX_VALUE or lower than Long.MIN_VALUE

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • @aioobe what you are trying to say? – Ruchira Gayan Ranaweera Sep 24 '14 at 08:09
  • *"If String is greater than Long.MAX_VALUE means that is no more a Long value"* -- I'm sure the OP knows this. The problem he is facing is that he can't check for overflows by doing `result>Long.MAX_VALUE` since `result` is a long. – aioobe Sep 24 '14 at 08:17
  • @RuchiraGayanRanaweera The problem is computer would believe overflowed data is legal format. And I'm allowed to use Long.parseLong because that's built-in library. – Chris Su Sep 24 '14 at 20:35