Kapparino
Kapparino

Reputation: 988

Regex matching decimal formatted number, with checks for count of numbers before and after decimal point

I may have a decimal formats like:

"#.#"
"#.##"
"#.00"
"##.###"
"##.000"
"###.###"
"#####.####"
"####.#####"
etc.

I want to validate a decimal formatted numbers[0-9] with 1 decimal point.

Additionally, I want to include this checks:

1) Before decimal point, there should be 0 or less or equal then the counted hash tags.

2) After decimal point, there should be 0 or less or equal then the counted hash tags.

For example:

Format definition is "##.###", and for this format, valid format numbers are those that have in this case, before decimal point, a 0 or less or equal than 2 numbers, 1 dot, and a 0 or less or equal than 3 numbers. Valid numbers are:

"1",
"12",
"12.3",
"12.34",
"12.345",

Invalid numbers are:

"1.3456", -- because there are 4 digits after decimal point
"12.34567", -- because there are 5 digits after decimal point
"123.3", -- because there are 3 digits before decimal point
"123.3454", -- because there are 3 digits before decimal point and 4 digits after decimal point

UPDATE:

Test

format: ###.###
    1. 12.34 -> result: matches; expected: matches
    2. 123.456 -> result: matches; expected: matches
    3. 123.4567 -> result: matches; expected: not matches
    4. 1234.567 -> result: not matches; expected: not matches
    5. 1234.5678 -> result: not matches; expected: not matches

Case 3. fails.

Code for testing patterns and numbers:

public static void main(String[] args) throws Exception
    {

        double[] initialValues = {
            12.34,
            123.456,
            123.4567,
            1234.567,
            1234.5678,

            0,
            1,
            12,
            123,

            0.1,
            0.123,
            123.0,

            1.2,
            1.23,
            1.234,

            1.2,
            12.3,
            123.4,

            123456.678,
            12345.6789,

            1.23456789
        };

        String[] decimalFormats = {
            "###.###",

            "#.#",
            "#.##",
            "#.###",

            "#.#",
            "##.#",
            "###.#",

            "###.###",
            "#####.#####"
        };
        new Main().testParsingNumber(initialValues, decimalFormats);
    }

    public void testParsingNumber(double[] initialValues, String[] decimalFormats) throws ParseException {
        for (String decimalFormat : decimalFormats) {
            System.out.println(decimalFormat);

            for (double initialValue : initialValues) {
                String formattedDecimalNumber = new DecimalFormat(decimalFormat).format(initialValue);
                System.out.println("\t" + initialValue + " -> " + (isValidDecimalNumber(formattedDecimalNumber, decimalFormat) ? "matches" : "not matches"));
            }

            System.out.println("\n");
        }
    }

    public boolean isValidDecimalNumber(String formattedDecimalNumber, String decimalFormat) {
        List<String> digits = Arrays.asList(decimalFormat.split("[.]"));
        int maxNumbersBeforeDecimal = digits.get(0).length();
        int maxNumbersAfterDecimal = digits.get(1).length();

        //[0-9]{1,"+x1+"} => match digit before the decimal point with occurrence 1-x1
        //[0-9]{0,"+x2+"} => match digit after the decimal point 0-x2
        //.{0,1} => match the decimal point

        Pattern regexPattern = Pattern.compile("^[0-9]{1,"+ maxNumbersBeforeDecimal +"}.{0,1}[0-9]{0,"+ maxNumbersAfterDecimal +"}$");
        Matcher matcher = regexPattern.matcher(doubleValue);
        return matcher.matches();
    }

Results:

###.###
    12.34 -> matches
    123.456 -> matches
    123.4567 -> matches -- This should return false. Not correct! Returns true.
    1234.567 -> not matches -- This should return false. Correct!
    1234.5678 -> not matches -- This should return false. Correct!
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> matches
    123.4 -> matches
    123456.678 -> not matches 
    12345.6789 -> not matches
    1.23456789 -> matches  -- Not correct


#.#
    12.34 -> not matches
    123.456 -> not matches
    123.4567 -> not matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches  -- Not correct
    123.0 -> matches  -- Not correct
    0.1 -> matches
    0.123 -> matches  -- Not correct
    123.0 -> matches  -- Not correct
    1.2 -> matches 
    1.23 -> matches  -- Not correct
    1.234 -> matches  -- Not correct
    1.2 -> matches
    12.3 -> not matches 
    123.4 -> not matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches  -- Not correct


#.##
    12.34 -> not matches
    123.456 -> not matches
    123.4567 -> not matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> not matches
    123.4 -> not matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


#.###
    12.34 -> not matches
    123.456 -> not matches
    123.4567 -> not matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> not matches
    123.4 -> not matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


#.#
    12.34 -> not matches
    123.456 -> not matches
    123.4567 -> not matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> not matches
    123.4 -> not matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


##.#
    12.34 -> matches
    123.456 -> not matches
    123.4567 -> not matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> matches
    123.4 -> not matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


###.#
    12.34 -> matches
    123.456 -> matches
    123.4567 -> matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> matches
    123.4 -> matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


###.###
    12.34 -> matches
    123.456 -> matches
    123.4567 -> matches
    1234.567 -> not matches
    1234.5678 -> not matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> matches
    123.4 -> matches
    123456.678 -> not matches
    12345.6789 -> not matches
    1.23456789 -> matches


#####.#####
    12.34 -> matches
    123.456 -> matches
    123.4567 -> matches
    1234.567 -> matches
    1234.5678 -> matches
    0.0 -> matches
    1.0 -> matches
    12.0 -> matches
    123.0 -> matches
    0.1 -> matches
    0.123 -> matches
    123.0 -> matches
    1.2 -> matches
    1.23 -> matches
    1.234 -> matches
    1.2 -> matches
    12.3 -> matches
    123.4 -> matches
    123456.678 -> not matches
    12345.6789 -> matches
    1.23456789 -> matches

Upvotes: 0

Views: 105

Answers (1)

Andrianekena Moise
Andrianekena Moise

Reputation: 1068

Here is my solution using regex :

    String x = "###.###";
    List<String> s = Arrays.asList(x.split("[.]"));
    int x1 = s.get(0).length();
    int x2 = s.get(1).length();

    //[0-9]{1,"+x1+"} => match digit before the decimal point with occurrence 1-x1
    //[0-9]{0,"+x2+"} => match digit after the decimal point 0-x2
    //.{0,1} => match the decimal point
    Pattern p = Pattern.compile("^[0-9]{1,"+x1+"}.{0,1}[0-9]{0,"+x2+"}$");

    Matcher matcher = p.matcher("123.33");
    System.out.println(matcher.matches());//true

Upvotes: 3

Related Questions