[奇淫怪巧] 利用正则表达式判断素数

最近在学习正则表达式,偶然间看到利用正则表达式判断一个数是不是素数的帖子。当时就震惊了,觉得好神奇。那个判断素数的函数是这样子的:

public static bool IsPrime(int i)
{
    return !Regex.IsMatch(new String(‘*‘, i), "^.?$|^(..+?)\\1+$");
}

有没有觉得很神奇?我当时就觉得相当的有想象力的一种实现。那让我们看一下这个正则表达式是如何做判断素数的。

  • 第一步,创建了一个长度为i,并以‘*‘填充的字符串。
  • 第二步,让这个后面的正则表达式去匹配这个字符串,如果匹配则不是质数。

过程很简单。让我们看一下这个正则表达式。

能被这个正则表达式匹配出则这个数不是素数,这个正则表达式可以分成两部分看,

  • 第一部分:^.?$^匹配字符串起始位置,$匹配字符串结束位置,.表示匹配单个任意字符,?表示可选。合起来的意思就是匹配只有一个字符或者没有字符的字符串,也就是0或者1。0或1不是质数,这里特殊匹配这两个数字。
  • 第二部分:^(..+?)\1+$。这部分是关键。先拆开来解释一下意思,^$就不解释了。(..+?)表示匹配两个及以上的任意字符,这里的+?表示它是忽略优先(lazy)的,对结果来说没有影响,出于性能考虑。注意到这个表达式有一个括号,这个是一个捕获型括号。\1是反向引用,引用的内容就是前面第一个括号选中的内容。那么后面\1+的意思就是匹配前面括号匹配中的内容一次或多次。

这个表达式基本内容解释完了,那么为什么能够匹配非素数呢?

匹配的过程大致是这样子的,(..+?)首先匹配2个字符,然后\1+匹配2的倍数个字符,如果能够匹配是不是就说明了这个数是2的倍数啦?当匹配失败的时候,匹配引擎将(..+?)匹配三个字符,然后\1+匹配3的倍数个字符,如果能够匹配则是3的倍数。依此类推。。。。。。

如果匹配了则说明这个数必定能够被某一个数整除,如果匹配完都没匹配到则说明从2到n-1的数都不能整除n,那就证明这个数是素数!

题外话

(..+?)?的作用,我认为这个是为了提高性能的。如果没有?的话(..+?)会试图把所有的字符都匹配完,然后发现后面还有表达式,于是从最后一个位置开始回溯。而加了?则是从第二个就开始往后去匹配。

打个比方:我们匹配12。^.?$|^(..+)\1+$会做的事情是先判断12是不是11的倍数、then 12是不是10的倍数........then 12是不是6的倍数。^.?$|^(..+?)\1+$会做的是先判断12是不是2的倍数,then 就没then了。对于素数的效率是一样的,因为每个位置都需要匹配过来,但是对于非素数从小开始匹配则能够让这个表达式早点结束匹配。

如果你觉得我解释的不清楚没明白,下面有其他人的解释:

[奇淫怪巧] 利用正则表达式判断素数

时间: 2024-10-25 08:18:29

[奇淫怪巧] 利用正则表达式判断素数的相关文章

你不知道的 docker 命令的奇淫怪巧

你不知道的 docker 命令的奇淫怪巧 Intro 介绍并收录一些可能会用到的一些简单实用却很少有人用的 docker 命令 dangling images build 自己的 docker 镜像的时候,有时会遇到用一个甚至多个中间层镜像,这会一定程度上减少最终打包出来 docker 镜像的大小,但是会产生一些tag 为 none 的无用镜像,也称为悬挂镜像 (dangling images) 列出所有的 dangling images: docker images -f "dangling=

你可能不知道的 docker 命令的奇淫怪巧

原文:你可能不知道的 docker 命令的奇淫怪巧 你可能不知道的 docker 命令的奇淫怪巧 Intro 介绍并收录一些可能会用到的一些简单实用却很少有人用的 docker 命令 dangling images build 自己的 docker 镜像的时候,有时会遇到用一个甚至多个中间层镜像,这会一定程度上减少最终打包出来 docker 镜像的大小,但是会产生一些tag 为 none 的无用镜像,也称为悬挂镜像 (dangling images) 列出所有的 dangling images:

奇淫怪巧之给Delphi的PrintDialog增加一个页码选定范围打印的Edit 转

奇淫怪巧之给Delphi的PrintDialog增加一个页码选定范围打印的Edit 在Delphi中使用PrintDialog打印对话框的时候,这个控件有三个选项,就是PrintRang那个属性的三个选项,其中有一个选项三,让我们自定义选择页码范围来打印.但是比较蛋疼的是,这个地方选中了之后啥子效果都没有.无法制定自己的页码范围,很是蛋疼.这里实际上应该要有一个Edit之类的编辑框的,这样可以让用户输入1,2,3-4之类的页码范围来整就比较人性化了.起初以为是自己没有指定某属性神马的导致,于是在

【Java】利用正则表达式判断是否为网址

本文与<[JavaScript]利用正则表达式检查输入框输入的是否为网址>(点击打开链接)为姊妹篇,在上文中已经提到了,正则表达式在各个程序是通用的,这里不再讲解正则表达式的具体用法.重点讲述正则表达式在Java中怎么使用,还是在判断是否为网址. 有以下的四个测试用例: 运行结果如上图所示. 代码如下: package urlReg; import java.util.regex.*; public class urlRegTest { public static void main(Stri

利用孪生素数判断素数

思路参见:http://blog.csdn.net/code_pang/article/details/7880245 孪生素数: 所谓孪生素数指的是间隔为 2 的相邻素数. 大于6以上的孪生素数, P-1和P+1为素数,则P-1和P+1一定为奇数,则P一定为偶数,即P为2的倍数! P-1.P.P+1为连续的自然数,他们一定有一个是3的倍数,P-1和P+1为素数,则他们不为3的倍数,即P也为3的倍数! 所以P一定为2和3的最小公倍数即6的倍数! n≥6且n-1和n+1为孪生素数,那么n一定是6的

利用正则表达式判断四则运算表达式是否合法

写了一个判断四则运算合法性较验的式子. public static bool CheckExpressionValid(string input) { string pattern = @"^(((?<o>\()[-+]?([0-9]+[-+*/])*)+[0-9]+((?<-o>\))([-+*/][0-9]+)*)+($|[-+*/]))*(?(o)(?!))$"; //去掉空格,且添加括号便于进行匹配 return Regex.IsMatch("

利用正则表达式判断Java中的秒钟、分钟、小时、日、月是否符合规则

// 定义校验规则 Pattern patRule = Pattern.compile("判断规则"); // 校验结果 patRule.matcher("判断的对象").matches(); 1.秒钟.分钟.小时判断规则 String smh = "([0-9]|[1-5][0-9]|59)"; 2.日校验规则 String dayRule= "([1-9]|[1-2][2-9]|[1-3][0-1])"; 3.月校验规则

[javascript 实践篇]——那些你不知道的“奇淫巧技”

1. 空(null, undefined)验证 刚开始,我是比较蠢的验证(我还真是这样子验证的) if (variable1 !== null || variable1 !== undefined || variable1 !== '') { let variable2 = variable1; } 大哥教会了我这样子验证,你会惊叹一下的 let variable2 = variable1 || ''; 如果你不信,在谷歌浏览器开发者面板的控制台下试试! //值为null的例子 let vari

CSS布局奇淫技巧之--各种居中

居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明外,都是兼容IE6+.谷歌.火狐等主流浏览器的. 先来说几种简单的.人畜无害的居中方法 1. 把margin设为auto 具体来说就是把要居中的元素的margin-left和margin-right都设为auto,此方法只能进行水平的居中,且对浮动元素或绝对定位元素无效. 2.使用 text-ali