【问题标题】:Regex matching decimal formatted number, with checks for count of numbers before and after decimal point正则表达式匹配十进制格式的数字,检查小数点前后的数字计数
【发布时间】:2019-02-26 10:44:21
【问题描述】:

我可能有十进制格式,例如:

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

我想验证带 1 个小数点的十进制格式的数字 [0-9]。

另外,我想包括以下检查:

1) 小数点前应小于等于计数的哈希标签。

2) 小数点后应有0或小于或等于计数的哈希标签。

例如:

格式定义为"##.###",对于这种格式,有效的格式数字是在这种情况下,在小数点之前,0 或小于或等于 2 个数字、1 个点和一个 0 或小于或等于超过3个数字。 有效数字是:

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

无效数字是:

"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

更新:

测试

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

案例 3. 失败。

测试模式和数字的代码:

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();
    }

结果:

###.###
    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.2有效,但是当输入为#.##时,数字1.2无效?
  • 是有效的,因为那个模式在小数点后有两个hash标签,而你的值只有1,所以它是balid。
  • new DecimalFormat(format).parse(input) 不是验证输入的更有效方法吗? (而不是先将格式转换为等效的正则表达式,然后在输入上测试该正则表达式)
  • 解析格式定义并获取点前后的长度,然后像 [1-9]{,lengthBeforeDot}.[1-9]{,lengthAfterDot} 一样编写您的 reg ex跨度>
  • 对于##.### 格式验证,OP 可以使用:^(?:\d+|\d{1,2}\.\d{1,3})$

标签: java regex validation


【解决方案1】:

这是我使用正则表达式的解决方案:

    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

【讨论】:

  • 当然,1111.111 如果您的格式类似于“###.###”,则返回 false。正则表达式模式[0-9]{1,3} 将数字的出现限制为3。我在测试时看到true。你试过了吗?
  • 我猜它不起作用,因为您格式化了initialValue。所以对于initialValue=123.4567 formattedDecimalNumber=123.457 然后它通过模式'###.###'的测试。像这样isValidDecimalNumber(String.valueOf(initialValue), decimalFormat) 调用isValidDecimalNumber 解决问题。
猜你喜欢
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
相关资源
最近更新 更多