RegEx для сопоставления математических выражений - PullRequest
0 голосов
/ 15 мая 2019

В настоящее время мне поручено проверить правильность форматирования данного выражения. Ex. «7x ^ 2 + 2x +1» пройдет, но «7x72» или что-то неправильно сформированное не получится.

Попытка

\d*x{0,1}(\^\d*){0,1}

Проверяет наличие каждой части функции, коэффициента, необязательного x, необязательного показателя степени. Я просто не уверен, как на самом деле отформатировать его, чтобы он был правильным для каждой части между знаками +/-, в противном случае функция не введена правильно.

Как мне решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

TL; DR Регулярное выражение:

(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?

Полный синтаксис будет:

[ ['-'][number]'x^2' ] ['+' | '-'] [ ['-'][number]'x' ] ['+' | '-'] [ ['-']number ]

['-'] означает необязательный знак минусдля числа.

[number] потому, что множитель 1 может быть опущен, даже если он -1, например, -x является допустимым сокращением для -1x.

['+' | '-'] означает + или -, помеченные как необязательные для простоты, но фактически они требуются между частями и не допускаются сами по себе.Это сложная часть, которая увеличит размер регулярного выражения.

Итак, давайте построим его:

part1: -?\d*x\^2
part2: -?\d*x
part3: -?\d+
OP   : \s*[+-]\s*(?!-)

(?!-) - запрет знака минус после оператора.

Остается [part1] [OP] [part2] [OP] [part3] с 3 дополнительными частями и двумя дополнительными операторами, за исключением того, что части должны быть разделены операторами, а операторы должны быть между частями, и должна присутствовать хотя бы одна часть.

Чтобы убедиться, что что-то присутствует, нам просто нужно предотвратить пустую строку, т.е. начать регулярное выражение с (?!$), ноль - с отрицательным предвкушением конца строки, иначе "в начале ввода, мы также нев конце ввода ".

В регулярном выражении мы делаем необязательное использование (?: xxx )?, то есть группа без захвата помечена как необязательная, поэтому сделать каждую часть и оператор необязательным легко.

Пока что мыпоэтому:

(?!$)(?:part1)?(?:OP)?(?:part2)?(?:OP)?(?:part3)?

Теперь для сложных деталей:

  • Детали должны быть разделены операторами

    Это проще всего проверить, если убедиться, что part2не сразу предшествует 2 (последнийсимвол part1), и этой части 3 непосредственно не предшествует 2 или x (последний символ part1 или part2), поэтому мы будем использовать отрицательные взгляды нулевой ширины.

    (?:(?<!2)part2)
    (?:(?<![2x])part3)
    
  • Операторы должны находиться между частями

    Операторы не могут быть первыми или последними

    (?:(?<!^)OP(?!^))
    

    Операторы не могут быть смежными, проще всего проверить, убедившись, что второму оператору непосредственно предшествует part1или part2, что делает избыточным «not at start».

    (?:(?<=[2x])OP)
    

    Для согласованности значение «not at start» для первого оператора может быть изменено на «must part1».

    (?:(?<=2)OP)
    

Это теперь дает нам (показано в нескольких строках для пояснения):

(?!$)
(?:part1)?
(?:(?<=2)OP(?!^))?
(?:(?<!2)part2)?
(?:(?<=[2x])OP(?!^))?
(?:(?<![2x])part3)?

Все вместе, с добавленными группами захвата для захвата (подписанных) чисел и операторов

(?!$)(?:(-?\d*)x\^2)?(?:(?<=2)\s*([+-])\s*(?!-|^))?(?:(?<!2)(-?\d*)x)?(?:(?<=[2x])\s*([+-])\s*(?!-|^))?(?:(?<![2x])(-?\d+))?

Вот он, закодированный на Java, с логикой для поиска a, b и c в формуле ax^2 + bx + c:

public static void main(String[] args) {
    System.out.println("part1 op1   part2 op2   part3   a  b  c  input");
    test("3x^2 + 4x + 5");
    test("x^2 + x + 1");
    test("x^2 - 4x");
    test("-x^2 - 1");
    test("-4x - 5");
    test("-3x^2");
    test("-4x");
    test("-5");
    test("");
    test("-3x^2 + -1x");
}
private static void test(String input) {
    String regex = "(?!$)" +
                   "(?:(-?\\d*)x\\^2)?" +
                   "(?:(?<=2)\\s*([+-])\\s*(?!-|^))?" +
                   "(?:(?<!2)(-?\\d*)x)?" +
                   "(?:(?<=[2x])\\s*([+-])\\s*(?!-|^))?" +
                   "(?:(?<![2x])(-?\\d+))?";
    Matcher m = Pattern.compile(regex).matcher(input);
    if (! m.matches()) {
        System.out.printf("%-41s\"%s\"%n", "No match", input);
    } else {
        String part1 = m.group(1);
        String op1   = m.group(2);
        String part2 = m.group(3);
        String op2   = m.group(4);
        String part3 = m.group(5);
        long a = parse(null, part1);
        long b = parse(op1, part2);
        long c = parse((op2 != null ? op2 : op1), part3);
        System.out.printf("%-6s%-6s%-6s%-6s%-6s%3d%3d%3d  \"%s\"%n",
                          (part1 == null ? "" : '"' + part1 + '"'),
                          (op1   == null ? "" : '"' + op1   + '"'),
                          (part2 == null ? "" : '"' + part2 + '"'),
                          (op2   == null ? "" : '"' + op2   + '"'),
                          (part3 == null ? "" : '"' + part3 + '"'),
                          a, b, c, input);
    }
}
private static long parse(String operator, String signedNumber) {
    long number;
    if (signedNumber == null)
        number = 0;
    else if (signedNumber.isEmpty())
        number = 1;
    else if (signedNumber.equals("-"))
        number = -1;
    else
        number = Long.parseLong(signedNumber);
    if ("-".equals(operator))
        number = -number;
    return number;
}

Выход

part1 op1   part2 op2   part3   a  b  c  input
"3"   "+"   "4"   "+"   "5"     3  4  5  "3x^2 + 4x + 5"
""    "+"   ""    "+"   "1"     1  1  1  "x^2 + x + 1"
""    "-"   "4"                 1 -4  0  "x^2 - 4x"
"-"   "-"               "1"    -1  0 -1  "-x^2 - 1"
            "-4"  "-"   "5"     0 -4 -5  "-4x - 5"
"-3"                           -3  0  0  "-3x^2"
            "-4"                0 -4  0  "-4x"
                        "-5"    0  0 -5  "-5"
No match                                 ""
No match                                 "-3x^2 + -1x"
1 голос
/ 15 мая 2019

Попробуйте это:

((-?\d+)x\^2\s*[+-]\s*)?(\d+)x\s*([+-]\s*\d+)
  • (-?\d+)x\^2\s*[+-]\s*)?
    • -?\d+ - знак 0 или 1 -, за которым следует одна или несколько цифр
    • x\^2 - символ x, символ ^, 2 символа
    • \s* - необязательный пробел
    • [+-] - либо + символ, либо - символ
    • ? - 0 или 1 из этой группы. Квадратичная формула может не иметь первой части. Удалите это ?, чтобы сделать его необязательным
  • (\d+)x - одна или несколько цифр, за которыми следует символ x (например, 2x)
  • \s* - дополнительное пространство
  • ([+-]\s*\d+)
    • [+ -] - либо + символ, либо - символ
    • \s* - дополнительное пространство
    • \d+ - одна или несколько цифр (например, 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...