0
votes

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
1
You mean to say that when the input is #.#, 1.2 is valid but when the input becomes #.##, the number 1.2 becomes invalid?Gurmanjot Singh
It will be valid, because that pattern has two hash tags after decimal point, and your value has only 1, so it will be balid.Kapparino
Wouldn't new DecimalFormat(format).parse(input) be a more effective way to validate the input? (rather than converting the format to an equivalent regex first and then testing that regex on the input)ernest_k
Parse the format definition and take length of before dot and after dot,then write your reg ex just like [1-9]{,lengthBeforeDot}.[1-9]{,lengthAfterDot}Y.Kakdas
For ##.### format validation, OP may use: ^(?:\d+|\d{1,2}\.\d{1,3})$anubhava

1 Answers

3
votes

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