Checking a float through a String

0

I'm trying, without using try-catch (I'm not allowed in this case), to know if a String is susceptible to being parsed to double, but it does not accept values, such as 1.80. This is the method:

private boolean alturaCorrecta() {
    boolean check = true;
    Character c;
    int control = 0;
    String cadena = TFAltura.getText();
    for (int i = 1; i < (TFAltura.getText().length()+1); i++) {
        c = cadena.charAt(i);
        if (!Character.isDigit(c)) {
            if (c.equals('.') && control == 0) {
                control++;
            } else if (control == 1) {
                check = false;
                break;
            }
            check = false;
            break;
        }
    }
    if(check){
        double valor=parseDouble(cadena);
        if (valor>1.50 && valor < 2.50){
           check=true; 
        }else{
            check = false;
            TAmensajes.setText("La altura debe estar comprendida entre 1.50 y 2.50");
        }
    }
    return check;
}
    
asked by Ald 28.11.2016 в 12:56
source

4 answers

1

Your detail is in the for cycle to verify the chain, try this way

for (int i = 0; i < (TFAltura.getText().length()); i++) {
    c = cadena.charAt(i);
    if (!Character.isDigit(c)) {
       if (c.equals('.') && control == 0) {
           control++;
       } else {
           check = false;
           break;
       }
    }
}
    
answered by 28.11.2016 в 15:54
1

The response of @ juandej18 works fine, and fixes your immediate problem of correctly determining that the "1.80" string can be parsed to double .

But, the difficulty with writing our own logic for this type of problem is that it is extremely difficult to do it correctly for all cases. For example, have you anticipated how to handle negative numbers?

So, by focusing on the most general and interesting question in your title: how can you verify if a string String can be parsed to double ?

Obviously, we all know that it can be done with a try-catch in this way:

public static void main(String args[])
{
    System.out.println(isValidDouble("1.80"));     // true
    System.out.println(isValidDouble("-1.80"));    // true
    System.out.println(isValidDouble("Infinity")); // true
    System.out.println(isValidDouble("NaN"));      // true
    System.out.println(isValidDouble("abc"));      // false
    System.out.println(isValidDouble("23.45.67")); // false
}

private static boolean isValidDouble(String s) {
    boolean isValid = true;

    try {
        Double.parseDouble(s);
    } catch(NumberFormatException nfe) {
        isValid = false;
    }

    return isValid;
}

Demo .

But you say you can not use a try-catch . And, in fact, if possible, it is always better to avoid using exceptions for normal situations. So I can not believe that Java still does not include an official method that can be called to do this verification without you throwing an exception. C #, for example, includes the TryParse method to handle this situation.

But interestingly, if you look in the documentation for Double.valueOf(s) , you will notice a section that says (translated):

  

To avoid calling this method with an invalid string and throwing a NumberFormatException , you can use the following regular expression to verify the string in advance:

... and then it gives you a long regular expression that you can use.

So, since the recommendation is in the official documentation, why not use it? It will surely work better than writing the logic on our own.

Here is an example of how to use it:

public static void main(String args[])
{
    System.out.println(isValidDouble("1.80"));     // true
    System.out.println(isValidDouble("-1.80"));    // true
    System.out.println(isValidDouble("Infinity")); // true
    System.out.println(isValidDouble("NaN"));      // true
    System.out.println(isValidDouble("abc"));      // false
    System.out.println(isValidDouble("23.45.67")); // false
}

private static boolean isValidDouble(String s) {
  final String Digits     = "(\p{Digit}+)";
  final String HexDigits  = "(\p{XDigit}+)";
  // an exponent is 'e' or 'E' followed by an optionally
  // signed decimal integer.
  final String Exp        = "[eE][+-]?"+Digits;
  final String fpRegex    =
      ("[\x00-\x20]*"+  // Optional leading "whitespace"
       "[+-]?(" + // Optional sign character
       "NaN|" +           // "NaN" string
       "Infinity|" +      // "Infinity" string

       // A decimal floating-point string representing a finite positive
       // number without a leading sign has at most five basic pieces:
       // Digits . Digits ExponentPart FloatTypeSuffix
       //
       // Since this method allows integer-only strings as input
       // in addition to strings of floating-point literals, the
       // two sub-patterns below are simplifications of the grammar
       // productions from section 3.10.2 of
       // The Java Language Specification.

       // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
       "((("+Digits+"(\.)?("+Digits+"?)("+Exp+")?)|"+

       // . Digits ExponentPart_opt FloatTypeSuffix_opt
       "(\.("+Digits+")("+Exp+")?)|"+

       // Hexadecimal strings
       "((" +
        // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "(\.)?)|" +

        // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "?(\.)" + HexDigits + ")" +

        ")[pP][+-]?" + Digits + "))" +
       "[fFdD]?))" +
       "[\x00-\x20]*");// Optional trailing "whitespace"

  return Pattern.matches(fpRegex, s);
}

Demo .

    
answered by 28.11.2016 в 17:13
0

Good, it would be good to specify a bit more what is the error that gives you, hitting for example the message of the exception in case there is.

On the other hand, for (int i = 1; i < (TFAltura.getText().length()+1); i++) { is very likely to throw you a IndexOutOfBoundsException since you will always try to find a position more than the maximum size you have.

Try putting for (int i = 0; i < TFAltura.getText().length(); i++) {

Anyway, as I said, try to specify a pco ams the error it gives you.

Greetings!

    
answered by 28.11.2016 в 14:13
0

Your logic is fine. The error that should be giving you as they say above is an ArrayOutBound Index

  String cadena = TFAltura.getText();
    for (int i = 1; i < (TFAltura.getText().length()+1); i++) {
        c = cadena.charAt(i);
        if (!Character.isDigit(c)) {
            if (c.equals('.') && control == 0) {
                control++;
            } else if (control == 1) {
                check = false;
                break;
            }
            check = false;
            break;
        }
    }

We are going through steps once we have defined our array when putting

  

for (int i = 1; i

answered by 28.11.2016 в 22:31