这个奇怪的JavaScript函数如何用于primality检查工作?

时间:2014-03-21 10:02:53

标签: javascript regex primes

这是功能:

var isPrime = function(x) {
    return (!(/^,?$|^(,,+?)\1+$/.test(Array(++x))));
};

它适用于小数字,但是当数字很大时,会抛出一个异常,表示数组长度无效。我无法理解这里发生了什么。 RegEx测试的作用是什么?为什么这段代码有效?

2 个答案:

答案 0 :(得分:9)

Array(++x)首先生成一串x逗号。

正则表达式现在:

^,?$         // Match 1 , or none
|            // or ...
^(,,+?)\1+$  // A specific number of commas, elaboration below:

逗号的数量至少等于2个逗号,然后重复直到结尾。它试图做的是:

  • 它首先尝试匹配2个逗号(,+?至少匹配1 ,懒惰),并使用它来匹配2的所有倍数,除了2本身因为{{的反向引用1}}是强制性的。因为\1匹配^(,,)\1+$的偶数,所以2的所有倍数都是。{/ p>

    旁注:,是一个反向引用,它将匹配第一个捕获组匹配的内容,在此初始情况\1中。因此,在第一阶段,(,,)将匹配2个逗号。

    如果匹配,则表示存在偶数个逗号且该数字不是素数。

  • 如果上面没有匹配,那么它会匹配3个逗号,并使用它来匹配3的所有倍数,再次,除了3本身。所有3的倍数,因为\1匹配^(,,,)\1+$的数字,为3的倍数。

    旁注:这一次,,将与\1匹配,因为现在它位于捕获组中。因此,在第二阶段,(,,,)将匹配3个逗号。

    如果匹配,则表示有多个逗号可以被3整除,因此不是素数。

等等。你可以看到模式吗?


因此,正则表达式实际上会检查从2开始的所有数字,直到\1的长度等于(,,+?)返回的数字。当然,对于大数字,您可能会遇到不同类型的错误:

  1. 传递给函数的数字对于正则表达式来说太大了,因为正则表达式试图在内存中保留太多东西,因此堆栈会溢出#34; s' s试图找到一个匹配"正如Floris在评论中提到的(这发生在node.js上的下一个错误之前);

  2. Array(++x)组成的数组有太多元素,JS不支持。

  3. 因此,如果正则表达式匹配,则它不是素数。这也是为什么你在开始时Array(++x)否定正则表达式测试结果的原因。

答案 1 :(得分:7)

Array(++x).toString()是一串x逗号。

这检查它是由以下两者组成的:

  • ,?:零或一个逗号
  • (,,+?)\1+:重复多个逗号至少2个

因此它检查x

  • 01
  • 或大于或等于2
  • 的数字的倍数

这是什么不是素数的定义。

更详细的解释:

  • /^A|B$:从开始到结束的A或B
  • ,?:逗号,可选(所以,0或1
  • (,,+?):一个或多个逗号,但不是贪心
  • \1+第一组重复一次或多次

请注意,没有什么魔力:它很昂贵,因为它要求引擎测试(,,+?)的所有可能大小,直到找到它为止。