开发者

Regex to find a float

I've never used regex before, but this java function requires it (shown here: How to set Edittext view allow only two numeric values and two decimal values like ##.##)

I basically just need to get a float from it the text box, should be simple. I used a tool and it said this should work:

String re1="([+-]?\\d*\\.\\d+)(?![-+0-9\\.])";

But it doesn't seem to be working, it doesn't let me put anything in the text box.

What's t开发者_运维问答he right way to do this? Thanks


Try this:

String re1="^([+-]?\\d*\\.?\\d*)$";


The right way for this problem isn't to use a regex, but just to use:

try {
     Float.parseFloat(string)
     return true;
}
catch (NumberFormatException ex) {
     return false;
}

Works perfectly fine, is the same code that is later used to parse the float and therefore bug free (or if it isn't we have a much bigger problem at hand).


After balking at the accepted answer (and the other two relevant ones), I decided to provide a new one. Then I found Christoffer Hammarström's Sep 1 '16 at 8:40 mostly hidden comment on Paulpro's answer (which was accepted).

Here's the accepted answer:

String re1="^([+-]?\d*\.?\d*)$";

Here's Christoffer's comment:

This matches the empty string, or a single dot, or a plus or a minus by itself.

In fact, none of the 3 answers that adhere to the requirement of the OP do a good job, which is that he must provide an RE to some other class object and allow an end user to type in any valid floating point number.

Here is my case for a new answer.

In summary, my answer is [+-]?(\d+|\d+\.\d+|\.\d+|\d+\.)([eE]\d+)?. You must add ^ at the beginning and $ at the end the expression if the class object might otherwise give a pass to invalid leading or trailing characters.

Here's how I read the expression as written above:

[+-]?

This means a leading sign character is allowed but not required.

( \d+ | \d+\.\d+ | \.\d+ | \d+\. )

I've added whitespace to make it easier to see what's going on. This means accept the 4 forms of commonly accepted expressions of signless non-scientific-notation floating point numbers. Many computer languages allow for all four. Perhaps with more grouping, this part of the expression could be compressed but at the expense of readability.

([eE]\d+)?

This final part means a scientific notation suffix is allowed by not required.

Here's all the code.

$ cat Tester.java | sed 's/^/    /'

import java.util.*;
import java.util.regex.*;

public class Tester {

    private class TestVal {
        private String  val;
        private boolean accepted;
        private boolean expect;
        private boolean tested;
        public TestVal (String testValue, boolean expectedResult) {
            val = testValue;
            expect = expectedResult;
            reset();
        }
        public String   getValue    () { return val; }
        public boolean  getExpect   () { return expect; }
        public void     reset       () { tested = false; accepted = false; }
        public boolean  getAccepted () { return accepted; }
        public boolean  getTested   () { return tested; }
        public void     setAccepted (boolean newAccept) { tested = true; accepted = newAccept; }
    }

    private ArrayList<TestVal> tests = new ArrayList<TestVal>();

    public void doRETest (Pattern re, TestVal tv) {
            boolean matches = re.matcher(tv.getValue()).matches();
            boolean ok = matches == tv.getExpect();
            String result = ok ? "success" : "fail";
            System.out.println(String.format("%10s matches=%5s: %s", tv.getValue(), matches, result));
            tv.setAccepted(ok);
    }

    private void testsSummary () {
        int skipped = 0;
        int passes = 0;
        int failures = 0;
        for (TestVal tv : tests)
            if (tv.getTested())
                if (tv.getAccepted())
                    passes++;
                else
                    failures++;
            else
                skipped++;
        System.out.println(String.format("\npassed %d tests, failed %d tests, and %d tests skipped\n\n", passes, failures, skipped));
    }

    public void doRETests (String re) {
        Pattern p = Pattern.compile(re);
        System.out.println(String.format("testing %s", re));
        for (TestVal tv : tests) {
            tv.reset();
            doRETest(p, tv);
        }
        testsSummary();
    }

    public Tester () {
        tests.add(new TestVal("1", true));
        tests.add(new TestVal(".1", true));
        tests.add(new TestVal("1.", true));
        tests.add(new TestVal("1.0", true));

        tests.add(new TestVal("+1", true));
        tests.add(new TestVal("+.1", true));
        tests.add(new TestVal("+1.", true));
        tests.add(new TestVal("+1.0", true));

        tests.add(new TestVal("-1", true));
        tests.add(new TestVal("-.1", true));
        tests.add(new TestVal("-1.", true));
        tests.add(new TestVal("-1.0", true));

        tests.add(new TestVal("1e2", true));
        tests.add(new TestVal(".1e2", true));
        tests.add(new TestVal("1.e2", true));
        tests.add(new TestVal("1.0e2", true));

        tests.add(new TestVal("1.0e2.3", false));
        tests.add(new TestVal(".", false));
        tests.add(new TestVal("", false));
        tests.add(new TestVal("+", false));
        tests.add(new TestVal("-", false));
        tests.add(new TestVal("a", false));
    }

    public static void main (String args[]) {
        Tester t = new Tester();

        String paulpro  = "^([+-]?\\d*\\.?\\d*)$";
        String lucac    = "^([+-]?(\\d+\\.)?\\d+)$";
        String armaj    = "\\d+\\.\\d+";
        String j6t7     = "[+-]?(\\d+|\\d+\\.\\d+|\\.\\d+|\\d+\\.)([eE]\\d+)?";

        t.doRETests(paulpro);
        t.doRETests(lucac);
        t.doRETests(armaj);
        t.doRETests(j6t7);

    }

}

And here's what happened when I executed it.

$ javac Tester.java && java Tester | sed 's/^/    /'

testing ^([+-]?\d*\.?\d*)$
         1 matches= true: success
        .1 matches= true: success
        1. matches= true: success
       1.0 matches= true: success
        +1 matches= true: success
       +.1 matches= true: success
       +1. matches= true: success
      +1.0 matches= true: success
        -1 matches= true: success
       -.1 matches= true: success
       -1. matches= true: success
      -1.0 matches= true: success
       1e2 matches=false: fail
      .1e2 matches=false: fail
      1.e2 matches=false: fail
     1.0e2 matches=false: fail
   1.0e2.3 matches=false: success
         . matches= true: fail
           matches= true: fail
         + matches= true: fail
         - matches= true: fail
         a matches=false: success

passed 14 tests, failed 8 tests, and 0 tests skipped


testing ^([+-]?(\d+\.)?\d+)$
         1 matches= true: success
        .1 matches=false: fail
        1. matches=false: fail
       1.0 matches= true: success
        +1 matches= true: success
       +.1 matches=false: fail
       +1. matches=false: fail
      +1.0 matches= true: success
        -1 matches= true: success
       -.1 matches=false: fail
       -1. matches=false: fail
      -1.0 matches= true: success
       1e2 matches=false: fail
      .1e2 matches=false: fail
      1.e2 matches=false: fail
     1.0e2 matches=false: fail
   1.0e2.3 matches=false: success
         . matches=false: success
           matches=false: success
         + matches=false: success
         - matches=false: success
         a matches=false: success

passed 12 tests, failed 10 tests, and 0 tests skipped


testing \d+\.\d+
         1 matches=false: fail
        .1 matches=false: fail
        1. matches=false: fail
       1.0 matches= true: success
        +1 matches=false: fail
       +.1 matches=false: fail
       +1. matches=false: fail
      +1.0 matches=false: fail
        -1 matches=false: fail
       -.1 matches=false: fail
       -1. matches=false: fail
      -1.0 matches=false: fail
       1e2 matches=false: fail
      .1e2 matches=false: fail
      1.e2 matches=false: fail
     1.0e2 matches=false: fail
   1.0e2.3 matches=false: success
         . matches=false: success
           matches=false: success
         + matches=false: success
         - matches=false: success
         a matches=false: success

passed 7 tests, failed 15 tests, and 0 tests skipped


testing [+-]?(\d+|\d+\.\d+|\.\d+|\d+\.)([eE]\d+)?
         1 matches= true: success
        .1 matches= true: success
        1. matches= true: success
       1.0 matches= true: success
        +1 matches= true: success
       +.1 matches= true: success
       +1. matches= true: success
      +1.0 matches= true: success
        -1 matches= true: success
       -.1 matches= true: success
       -1. matches= true: success
      -1.0 matches= true: success
       1e2 matches= true: success
      .1e2 matches= true: success
      1.e2 matches= true: success
     1.0e2 matches= true: success
   1.0e2.3 matches=false: success
         . matches=false: success
           matches=false: success
         + matches=false: success
         - matches=false: success
         a matches=false: success

passed 22 tests, failed 0 tests, and 0 tests skipped


This is the correct way:

String floatRegexp="^([+-]?(\\d+\\.)?\\d+)$";

or if you look also in the middle of other text:

String floatRegexp="([+-]?(\\d+\\.)?\\d+)";

and if you don't look for the minus/plus sign:

String floatRegexp="^(\\d+\\.)?\\d+$";


this answer is from Johan Sjöberg https://stackoverflow.com/a/12235002/4035655

You could try matching the digits using a regular expression

\\d+\\.\\d+

This could look something like

Pattern p = Pattern.compile("\\d+\\.\\d+");
Matcher m = p.matcher("Sstring>26.0.[2.3.2.3D] .352.(f) 1)"503B"(\1.67>>Sstring");
while (m.find()) {
    System.out.println(Float.parseFloat(m.group()));
}

the output is:

26.0
2.3
2.4
1.67

the part [2.3.2.3D] of the string is split into two separate float numbers


String floatRegex = "[+-]?\\d*([.]?\\d+)";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜