我在RosettaCode上找到了以下Java代码示例:

public static boolean prime(int n) {
  return !new String(new char[n]).matches(".?|(..+?)\\1+");
}
  • 我特别不了解Java,但除了正则表达式本身之外,还要理解这个片段的所有方面
  • 当你在内置的PHP函数中找到它时,我有基本的高级Regex知识

怎么样.?|(..+?)\\\\1+匹配素数?

#1楼 票数:116 已采纳

你说你理解这部分,但只是强调,生成的字符串的长度等于提供的数字。 所以当且仅当n == 3 ,字符串有三个字符。

.?

正则表达式的第一部分说,“任何字符,零或一次”。 所以基本上,有零个或一个字符 - 或者,根据我上面提到的, n == 0 || n == 1 n == 0 || n == 1 如果我们有匹配,那么返回否定。 这与零和一个不是素数的事实相对应。

(..+?)\\1+

正则表达式的第二部分有点棘手,依赖于组和反向引用。 一个组是括号中的任何内容,然后由正则表达式引擎捕获并存储以供以后使用。 反向引用是稍后在同一个正则表达式中使用的匹配组。

该组捕获1个字符,然后捕获任何字符中的1个或多个字符。 (+字符表示一个或多个,但仅限于前一个字符或组。所以这不是“两个或四个或六个等字符”,而是“两个或三个等”。+?类似+,但它试图匹配尽可能少的字符。+如果可以的话,通常会尝试吞噬整个字符串,这在这种情况下很糟糕,因为它会阻止反向引用部分工作。)

下一部分是反向引用:同一组字符(两个或更多)再次出现。 所述反向引用出现一次或多次。

所以。 捕获的组对应于捕获的自然数量的字符(从2开始)。 然后,所述组出现一些自然次数(也从2开始)。 如果存在匹配,则意味着可以找到两个大于或等于2的数字与n长度字符串匹配的乘积...意味着您有一个复合n。 所以再次,回到成功匹配的否定:n不是素数。

如果找不到匹配,那么你就无法得到一个大于或等于2的两个自然数的乘积...并且你有一个不匹配和一个素数,因此再次返回否定匹配结果。

你现在看到了吗? 这是令人难以置信的棘手(而且计算成本很高!)但是一旦你得到它,它同时也很简单。 :-)

如果你有进一步的问题,我可以详细说明,比如正则表达式解析实际上是如何工作的。 但我现在试图让这个答案变得简单(或者尽可能简单)。

#2楼 票数:71

我将解释素性测试外的正则表达式的一部分:下面的正则表达式,给定String s其由重复的String t ,认定t

    System.out.println(
        "MamamiaMamamiaMamamia".replaceAll("^(.*)\\1+$", "$1")
    ); // prints "Mamamia"

它的工作方式是正则表达式将(.*)捕获到\\1 ,然后查看是否有\\1+跟随它。 使用^$可确保匹配必须是整个字符串。

因此,在某种程度上,我们给出了String s ,这是String t的“倍数”,正则表达式将找到这样的t (最长的,因为\\1是贪婪的)。

一旦你理解了这个正则表达式的工作原理,那么(暂时忽略OP正则表达式中的第一个替代)解释它如何用于素性测试很简单。

  • 要测试n素数,首先生成一个长度为nString (用相同的char填充)
  • 正则表达式将一些长度的String (比如k )捕获到\\1 ,并尝试将\\1+String的其余部分匹配
    • 如果存在匹配,则nk的适当倍数,因此n不是素数。
    • 如果没有匹配,则不存在除n这样的k ,因此n是素数

怎么样.?|(..+?)\\1+匹配素数?

实际上,它没有! 匹配长度不是素数的String

  • .? :交替的第一部分匹配长度为01 String (根据定义不是素数)
  • (..+?)\\1+ :交替的第二部分,即上面解释的正则表达式的变体,匹配长度为n String ,它是长度为k >= 2String的“倍数”(即n是a复合,而不是素数)。
    • 注意不情愿的修饰符? 实际上并不需要正确性,但它可能有助于通过首先尝试较小的k加速该过程

注意! return语句中的boolean complement运算符:它否定matches 当正则表达式匹配时, n是素数! 这是一个双重否定的逻辑,所以难怪它有点令人困惑!


简单化

这是对代码的简单重写,使其更具可读性:

public static boolean isPrime(int n) {
    String lengthN = new String(new char[n]);
    boolean isNotPrimeN = lengthN.matches(".?|(..+?)\\1+");
    return !isNotPrimeN;
}

以上内容基本上与原始Java代码相同,但分解为多个语句,并赋予局部变量赋值以使逻辑更易于理解。

我们还可以使用有限重复来简化正则表达式,如下所示:

boolean isNotPrimeN = lengthN.matches(".{0,1}|(.{2,})\\1+");

同样,给定一个长度为nString ,填充相同的char

  • .{0,1}检查n = 0,1 ,不是素数
  • (.{2,})\\1+检查n是否是k >= 2 ,NOT prime的正确倍数

除了不情愿的修饰语? \\1 (为清晰起见省略),上述正则表达式与原始正则表达式相同。


更有趣的正则表达式

以下正则表达式使用类似的技术; 它应该是教育的:

System.out.println(
    "OhMyGod=MyMyMyOhGodOhGodOhGod"
        .replaceAll("^(.+)(.+)(.+)=(\\1|\\2|\\3)+$", "$1! $2! $3!")
); // prints "Oh! My! God!"

也可以看看

#3楼 票数:25

很好的正则表达技巧(虽然非常低效)... :)

正则表达式定义非素数如下:

当且仅当N <= 1或N被某些K> 1整除时,N不是素数。

不是将N的简单数字表示传递给正则表达式引擎,而是向其提供由重复字符组成的长度为 N的序列。 析取的第一部分检查N = 0或N = 1,第二部分使用反向引用来寻找除数K> 1。 它强制正则表达式引擎找到一些非空的子序列,该子序列可以重复至少两次以形成序列。 如果存在这样的子序列,则意味着其长度除以N,因此N不是素数。

#4楼 票数:3

/^1?$|^(11+?)\1+$/

转换为基数1后应用于数字(1 = 1,2 = 11,3 = 111,...)。 非素数将与此匹配。 如果不匹配,那就是素数。

这里解释。

  ask by kitlite translate from so

未解决问题?本站智能推荐:

2回复

此正则表达式如何查找素数? [重复]

可能重复: 如何确定数字是否为正则表达式的质数? 此页面声称此正则表达式发现非素数(并通过反示例:质数): 如何找到素数?
1回复

正则表达式 - 这个正则表达式用于素数检测的复杂性是多少?

这行ruby代码检测素数(太棒了!)。 详细信息请参阅此博客文章http://www.noulakaz.net/weblog/2007/03/18/a-regular-expression-to-check-for-prime-numbers/ 我很好奇它以BIG-O表示法的方式表
6回复

如何确定一个数字是否为素数

好吧,我的问题不是如何弄清楚一个数字是否是素数,因为我认为我想出来了,但更多的是如何让它正确显示。 这是我的代码: 现在我的问题是,如果数字最终是9,它会说它是一个素数,它不是。 我认为问题是中断在一个循环后停止它所以它不是递增变量p所以它只测试除以2(我认为)。 但是如果我删
2回复

这个正则表达式如何工作?

从这篇文章来看, /^1?$|^(11+?)\\1+$/检查一个数字(它在一元中的值)是否为素数。 使用这个, perl -l -e '(1 x $_) !~ /^1?$|^(11+?)\\1+$/ && print while ++$_;' 返回素数列表。
3回复

如何确定两个数字是否相对素数?

我正在尝试编写一种方法来计算两个数字是否相对于赋值的素数。 我主要是寻找从哪里开始的答案。 我知道有一个方法gcd()会为我做很多事情,但是这个任务很可能让我在没有gcd或数组的情况下做到这一点。 我有点开始了,因为我知道我必须在for循环中使用%运算符。 显然,这种方法只会返
2回复

如何确定一个数字是否为二进制数并且只有一个正则表达式且有偶数个零?

我想要一个正则表达式来确定一个数字是否是二进制的,以及它是否有偶数个零。 例如,如果我们考虑这 3 个数字: 10001010 00010010 45671892 我希望正则表达式匹配以下内容: 10001010 //不匹配,因为它的零数量不均匀 0001001
2回复

我怎样才能让这个代码打印一个数字中有多少个素数?

我遇到的问题与到目前为止我得到的每个响应之间的区别在于,我试图让代码打印出有多少个数字是素数,而不是原始数字中有多少个素数。 例如,如果用户输入 567,我需要测试 5、6 和 7 并判断有多少是质数。 无论如何 - 我试图让这个代码打印用户输入的数字中有多少个素数。 当我运行它时,它会打印该数字
2回复

为什么我们在获得素数时不必检查数字是否为素数?

这是寻找素因子的典型代码: 我的问题是为什么在将它添加到列表之前我们不检查我是否是素数?