Как работает это регулярное выражение?
От в этой статье,
/^1?$|^(11+?)\1+$/
проверяет, является ли число (его значение в унарном) простым или нет.
Используя это, perl -l -e '(1 x $_) !~ /^1?$|^(11+?)\1+$/ && print while ++$_;'
возвращает список простых чисел.
У меня недостаточно опыта работы с Perl, но я понимаю, что регулярное выражение будет true для числа, которое не является простым. Итак, если мы напечатаем все числа, которые не выражают true с этим выражением, у нас есть список простых чисел. То, что пытается выполнить запрос perl.
О части регулярного выражения,
^1?$
часть предназначена для подсчета 1 как не просто
^(11+?)\1+$
предназначен для сопоставления не простых чисел, начиная с 4.
То, что я не понимаю, - это то, что ?
в регулярном выражении вообще необходимо.
По мне /^1$|^(11+)\1+$/
должно быть просто отлично и на самом деле
perl -l -e '(1 x $_) !~ /^1$|^(11+)\1+$/ && print while ++$_;'
дает мне тот же набор простых чисел.
Есть ли недостаток в моем понимании регулярного выражения? Почему нужен ?
?
Не соответствует ли ?
нулю или одному вхождению предшествующего ему выражения?
Ответы
Ответ 1
Первый ?
предназначен для сопоставления пустой строки (т.е. 0) как непростой. Если вам все равно, соответствует ли регулярное выражение 0, то это необязательно.
Второй ?
предназначен только для эффективности. +
обычно "жадный", что означает, что он соответствует количеству символов, доступных, а затем возвращается, если остальное регулярное выражение не соответствует. +?
делает его неживым, поэтому он соответствует только 1 символу, а затем пытается сопоставить больше, если остальная часть регулярного выражения не соответствует. (См. раздел Quantifiers perlre для получения более подробной информации о жадных и нежелательных соответствиях.)
В этом конкретном регулярном выражении (11+?)
означает, что он проверяет делимость на 2 ('11'
), затем 3 ('111'
), затем 4 и т.д. Если вы использовали (11+)
, он проверил делимость на N (само число), затем N-1, затем N-2 и т.д. Так как делитель должен быть не больше N/2, без ?
он будет тратить время на тестирование множества "потенциальных" делителей, возможно, работает. Это все равно будет соответствовать нечетным числам, только медленнее. (Кроме того, $1
будет самым большим делителем, а не самым маленьким.)
Ответ 2
Первый ?
сделает "" (пустая строка, унарный ноль) не будет простым числом. Нуль определяется как не простое.
Второе - другое; он останавливает регулярное выражение от жадного соответствия. Это должно значительно улучшить производительность матча, так как первая часть этого раздела ((11+)
) не будет потреблять почти всю строку, прежде чем будет возвращаться. Если вы опускаете вопросительный знак, вы эффективно проверяете, делится ли нечетный n
на n-1
, и поэтому один вниз; если вы включите его, вы тестируете делимость на два первых и так далее. Очевидно, что числа, как правило, делятся на более мелкие факторы чаще, поэтому ваш матч будет быстрее.