stringToDouble(String s) throws NumberFormatException { final int radix = 10;
public static double stringToDouble(String s) throws NumberFormatException { final int radix = 10;
   stringToDouble(String s)      throws NumberFormatException      {       final int radix = 10; // assume radix = 10       if (s == null)         throw new NumberFormatException("null");       int i = 0, max = s.length()-1;       if (max < 0)         throw new NumberFormatException("empty string");       // Scan past any whitespace.       //while (Character.isWhiteSpace(s.charAt(i))) ++i;       // Figure out sign.       boolean sign = false; // positive       char c = s.charAt(i);       if (c == '+') {         if (i == max) throw new NumberFormatException(s);         c = s.charAt(++i);       } else if (c == '-') {         sign = true;         if (i == max) throw new NumberFormatException(s);         c = s.charAt(++i);       }       int atLeast = i;       // must be at least one digit (comment this out if you don't care)       if ((c != '.') && !Character.isDigit(c)) throw new NumberFormatException(s);       // Parse number.       double val = 0;     doExponent: // this label is so we can simulate 'goto'       for (;;) {         // c is already initialized at this point.         if ((c == 'e') || (c == 'E')) break doExponent;         if (c == '.') {           // must be at least one digit (comment this out if you don't care)           if (max == atLeast) throw new NumberFormatException(s);           if (i == max) return (sign ? -val : val);           // start parsing to the right of the decimal point.           c = s.charAt(++i);           // must be at least one digit (comment this out if you don't care)           if ((i == atLeast+1) && !Character.isDigit(c)) throw new NumberFormatException(s);           int powIndex = 0;           int newMax = i + negPowersOf10.length;           for (;;) {             if ((c == 'e') || (c == 'E')) break doExponent;             int digit = Character.digit(c, radix);             if (digit < 0) {               // we reached a non-digit before the end of the string.               if ((i == max) &&                   ((c == 'f') || (c == 'F') || (c == 'd') || (c == 'D')))                 return (sign ? -val : val);               // not acceptable!               throw new NumberFormatException(s);             }             val += negPowersOf10[powIndex] * digit;             if (i == newMax) break;             if (i == max) return (sign ? -val : val);             ++powIndex;             c = s.charAt(++i);           }           // throw away insignificant digits.           for (;;) {             if ((c == 'e') || (c == 'E')) break doExponent;             int digit = Character.digit(c, radix);             if (digit < 0) {               // we reached a non-digit before the end of the string.               if ((i == max) &&                   ((c == 'f') || (c == 'F') || (c == 'd') || (c == 'D')))                 return (sign ? -val : val);               // not acceptable!               throw new NumberFormatException(s);             }             if (i == max) return (sign ? -val : val);             c = s.charAt(++i);           }         } else {           // still left of decimal place / exponent.           int digit = Character.digit(c, radix);           if (digit < 0) {             // we reached a non-digit before the end of the string.             if ((i == max) &&                 ((c == 'f') || (c == 'F') || (c == 'd') || (c == 'D')))               return (sign ? -val : val);             // not acceptable!             throw new NumberFormatException(s);           }           val *= 10;           val += digit;           if (i == max) return (sign ? -val : val);           c = s.charAt(++i);         }       }       if (i == max) throw new NumberFormatException(s);       // now, handle the exponent.       c = s.charAt(++i);       // find sign       boolean expsign = false;       if (c == '+') {         if (i == max) throw new NumberFormatException(s);         c = s.charAt(++i);       } else if (c == '-') {         expsign = true;         if (i == max) throw new NumberFormatException(s);         c = s.charAt(++i);       }       // must be at least one digit.       if (!Character.isDigit(c)) throw new NumberFormatException(s);       int exp = 0;       for (;;) {         int digit = Character.digit(c, radix);         if (digit < 0) {           // we reached a non-digit before the end of the string.           if ((i == max) &&               ((c == 'f') || (c == 'F') || (c == 'd') || (c == 'D'))) {           } else {             // not acceptable!             throw new NumberFormatException(s);           }         } else {           exp *= 10;           exp += digit;         }         if (i == max) {           // note: can change this to do 'smart' exponentiation in lg time.           // its probably not worth it -- when exponents are big, the number           // quickly goes to infinity or 0, at which point it stops anyways.           if (expsign) {             // question: could we ever get a 'NaN' here?             while ((exp != 0) && /*(val != NaN) &&*/ (val != 0.0)) {               if (exp >= 32)      { val *= negPowersOf10[31]; exp -= 32; }               else if (exp >= 16) { val *= negPowersOf10[15]; exp -= 16; }               else if (exp >= 8)  { val *= negPowersOf10[7];  exp -= 8;  }               else if (exp >= 4)  { val *= negPowersOf10[3];  exp -= 4;  }               else if (exp >= 2)  { val *= negPowersOf10[1];  exp -= 2;  }               else                { val *= negPowersOf10[0];  exp -= 1;  }             }           } else {             // question: could we ever get a 'NaN' here?             while ((exp != 0) && /*(val != NaN) &&*/ (val != Double.POSITIVE_INFINITY)) {               if (exp >= 32)      { val *= posPowersOf10[31]; exp -= 32; }               else if (exp >= 16) { val *= posPowersOf10[15]; exp -= 16; }               else if (exp >= 8)  { val *= posPowersOf10[7];  exp -= 8;  }               else if (exp >= 4)  { val *= posPowersOf10[3];  exp -= 4;  }               else if (exp >= 2)  { val *= posPowersOf10[1];  exp -= 2;  }               else                { val *= posPowersOf10[0];  exp -= 1;  }             }           }           return (sign ? -val : val);         }         c = s.charAt(++i);       }     }