检查素数的正则表达式
2010-07-27 11:05
417 查看
一般来说,我们会使用正规表达式来做字符串匹配,今天在网上浏览的时候,看到了有人用正则表达式来检查一个数字是否为素数(质数),让我非常感兴趣,这个正则表达式如入所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/2015/2015030184/ffe4a6fb537706a2faeb4a6561d7befd.jpg)
检查素数与否的正则表达式
要使用这个正规则表达式,你需要把自然数转成多个1的字符串,如:2 要写成 “11”, 3 要写成 “111”, 17 要写成“11111111111111111”,这种工作使用一些脚本语言可以轻松的完成。
一开始我对这个表达式持怀疑态度,但仔细研究了一下这个表达式,发现是非常合理的,下面,让我带你来细细剖析一下是这个表达式的工作原理。
首先,我们看到这个表达式中有“|”,也就是说这个表达式可以分成两个部分:/^1?$/ 和 /^(11+?)/1+$/
第一部分:/^1?$/, 这个部分相信不用我多说了,其表示匹配“空串”以及字串中只有一个“1”的字符串。
第二部分:/^(11+?)/1+$/,这个部分是整个表达式的关键部分。其可以分成两个部分,(11+?) 和/1+$,前半部很简单了,匹配以“11”开头的并重复0或n个1的字符串,后面的部分意思是把前半部分作为一个字串去匹配还剩下的字符串1次或多次(这句话的意思是——剩余的字串的1的个数要是前面字串1个数的整数倍)。
可见这个正规则表达式是取非素数,要得到素数还得要对整个表达式求反。通过上面的分析,我们知道,第二部分是最重要的,对于第二部分,举几个例子,
示例一:判断自然数8。我们可以知道,8转成我们的格式就是“11111111”,对于(11+?),其匹配了“11”,于是还剩下“111111”,而/1+$正好匹配了剩下的“111111”,因为,“11”这个模式在“111111”出现了三次,符合模式匹配,返回true。所以,匹配成功,于是这个数不是质数。
示例二:判断自然数11。转成我们需要的格式是“11111111111”(十一个1),对于(11+?),其匹配了“11”(前两个1),还剩下“111111111”(九个1),而/1+$无法为“11”匹配那“九个1”,因为“11”这个模式并没有在“九个1”这个串中正好出现N次。于是,我们的正则表达式引擎会尝试下一种方法,先匹配“111”(前三个1),然后把“111”作为模式去匹配剩下的“11111111”(八个1),很明显,那“八个1”并没有匹配“三个1”多次。所以,引擎会继续向下尝试……直至尝试所有可能都无法匹配成功。所以11是素数。
通过示例二,我们可以得到这样的等价数算算法,正则表达式会匹配这若干个1中有没有出现“二个1”的整数倍,“三个1”的整数倍,“四个1”的整数倍……,而,这正好是我们需要的算素数的算法。现在大家明白了吧。
下面,我们用perl来使用这个正规则表达式不停地输出素数:(关于perl的语法我就不多说了,请注意表达式前的取反操作符)
另外,让我们来举一反三,根据上述的这种方法,我们甚至可以用正则表达式来求证某方式是否有解,如:
二元方程:17x + 12y = 51 判断其是否有解的正则表达式是:^(.*)/1{16}(.*)/2{11}$
三元方程:11x + 2y + 5z = 115 判断其是否有解的正则表达式是:^(.*)/1{10}(.*)/2{1}(.*)/3{4}$
![](https://oscdn.geek-share.com/Uploads/Images/Content/2015/2015030184/ffe4a6fb537706a2faeb4a6561d7befd.jpg)
检查素数与否的正则表达式
要使用这个正规则表达式,你需要把自然数转成多个1的字符串,如:2 要写成 “11”, 3 要写成 “111”, 17 要写成“11111111111111111”,这种工作使用一些脚本语言可以轻松的完成。
一开始我对这个表达式持怀疑态度,但仔细研究了一下这个表达式,发现是非常合理的,下面,让我带你来细细剖析一下是这个表达式的工作原理。
首先,我们看到这个表达式中有“|”,也就是说这个表达式可以分成两个部分:/^1?$/ 和 /^(11+?)/1+$/
第一部分:/^1?$/, 这个部分相信不用我多说了,其表示匹配“空串”以及字串中只有一个“1”的字符串。
第二部分:/^(11+?)/1+$/,这个部分是整个表达式的关键部分。其可以分成两个部分,(11+?) 和/1+$,前半部很简单了,匹配以“11”开头的并重复0或n个1的字符串,后面的部分意思是把前半部分作为一个字串去匹配还剩下的字符串1次或多次(这句话的意思是——剩余的字串的1的个数要是前面字串1个数的整数倍)。
可见这个正规则表达式是取非素数,要得到素数还得要对整个表达式求反。通过上面的分析,我们知道,第二部分是最重要的,对于第二部分,举几个例子,
示例一:判断自然数8。我们可以知道,8转成我们的格式就是“11111111”,对于(11+?),其匹配了“11”,于是还剩下“111111”,而/1+$正好匹配了剩下的“111111”,因为,“11”这个模式在“111111”出现了三次,符合模式匹配,返回true。所以,匹配成功,于是这个数不是质数。
示例二:判断自然数11。转成我们需要的格式是“11111111111”(十一个1),对于(11+?),其匹配了“11”(前两个1),还剩下“111111111”(九个1),而/1+$无法为“11”匹配那“九个1”,因为“11”这个模式并没有在“九个1”这个串中正好出现N次。于是,我们的正则表达式引擎会尝试下一种方法,先匹配“111”(前三个1),然后把“111”作为模式去匹配剩下的“11111111”(八个1),很明显,那“八个1”并没有匹配“三个1”多次。所以,引擎会继续向下尝试……直至尝试所有可能都无法匹配成功。所以11是素数。
通过示例二,我们可以得到这样的等价数算算法,正则表达式会匹配这若干个1中有没有出现“二个1”的整数倍,“三个1”的整数倍,“四个1”的整数倍……,而,这正好是我们需要的算素数的算法。现在大家明白了吧。
下面,我们用perl来使用这个正规则表达式不停地输出素数:(关于perl的语法我就不多说了,请注意表达式前的取反操作符)
1 | perl -e '$|++;(1 x$_)!~/^1?$|^(11+?)/1+$/&&print"$_ "while ++$_' |
二元方程:17x + 12y = 51 判断其是否有解的正则表达式是:^(.*)/1{16}(.*)/2{11}$
三元方程:11x + 2y + 5z = 115 判断其是否有解的正则表达式是:^(.*)/1{10}(.*)/2{1}(.*)/3{4}$
相关文章推荐
- [转]检查素数的正则表达式
- 检查素数的正则表达式
- 检查素数的正则表达式
- 利用正则表达式检查素数
- 检查素数的正则表达式[转]
- 检查素数的正则表达式分享
- 检查素数的正则表达式
- 检查素数的正则表达式
- 检查素数的正则表达式分享
- Python 正则表达式验证是否为素数
- 使用CAtlRegExp正则表达式检查浮点数输入
- dd/mm/yyyy格式有效日期检查的正则表达式
- 通过例子学习正则表达式(二)--检查输入的"钱"
- 检查字符串长度 检查字符串是否为空 用正则表达式验证出版物的ISBN号 用正则表达式验证邮证编码 验证字符串中是否含有汉字
- 正则表达式(检查用户名、密码、电话号码)
- 正则表达式判断质数(素数)的代码
- Visual Studio 使用正则表达式检查代码规范
- 比较全面的Email正则表达式、对于特殊的邮箱Email也可以检查
- js---全面正则表达式语法,常用正则检查表达式手机号email地址url检查
- 【转】通过例子学习正则表达式(二)--检查输入的"钱"