通常來講,咱們會使用正規表達式來作字符串匹配,今天在網上瀏覽的時候,看到了有人用正則表達式來檢查一個數字是否爲素數(質數),讓我很是感興趣,這個正則表達式如入所示:正則表達式
檢查素數與否的正則表達式算法
要使用這個正規則表達式,你須要把天然數轉成多個1的字符串,如:2 要寫成 「11」, 3 要寫成 「111」, 17 要寫成「11111111111111111」,這種工做使用一些腳本語言能夠輕鬆的完成。shell
一開始我對這個表達式持懷疑態度,但仔細研究了一下這個表達式,發現是很是合理的,下面,讓我帶你來細細剖析一下是這個表達式的工做原理。spa
首先,咱們看到這個表達式中有「|」,也就是說這個表達式能夠分紅兩個部分:/^1?$/ 和 /^(11+?)\1+$/code
可見這個正規則表達式是取非素數,要獲得素數還得要對整個表達式求反。經過上面的分析,咱們知道,第二部分是最重要的,對於第二部分,舉幾個例子,blog
示例一:判斷天然數8。咱們能夠知道,8轉成咱們的格式就是「11111111」,對於(11+?),其匹配了「11」,因而還剩下「111111」,而\1+$正好匹配了剩下的「111111」,由於,「11」這個模式在「111111」出現了三次,符合模式匹配,返回true。因此,匹配成功,因而這個數不是質數。ci
示例二:判斷天然數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」的整數倍……,而,這正好是咱們須要的算素數的算法。如今你們明白了吧。get
下面,咱們用perl來使用這個正規則表達式不停地輸出素數:(關於perl的語法我就很少說了,請注意表達式前的取反操做符)string
1
|
perl -e
'$|++;(1 x$_)!~/^1?$|^(11+?)\1+$/&&print"$_ "while ++$_'
|
另外,讓咱們來觸類旁通,根據上述的這種方法,咱們甚至能夠用正則表達式來求證某方式是否有解,如:
你們不妨本身作作練習,爲何上述的兩個正則表達式能夠判斷方程是否有解。若是沒法參透其中的奧妙的話,你能夠讀讀這篇英文文章。
(全文完)
(轉載本站文章請註明做者和出處 酷 殼 – CoolShell.cn ,請勿用於任何商業用途)