本帖最後由 遇見sharon 於 2013-8-12 17:09 編輯
一般來說,我們會使用正規表示式來做字串匹配,今天在網上瀏覽的時候,看到了有人用正規表示式來檢查乙個數字是否為素數(質數),讓我非常感興趣,這個正規表示式如入所示:
要使用這個正規則表示式,你需要把自然數轉成多個1的字串,如:2 要寫成 「11」, 3 要寫成 「111」, 17 要寫成「11111111111111111」,這種工作使用一些指令碼語言可以輕鬆的完成。
一開始我對這個表示式持懷疑態度,但仔細研究了一下這個表示式,發現是非常合理的,下面,讓我帶你來細細剖析一下是這個表示式的工作原理。
首先,我們看到這個表示式中有「|」,也就是說這個表示式可以分成兩個部分:/^1?$/ 和 /^(11+?)\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的語法我就不多說了,請注意表示式前的取反操作符)
perl -e'$|++;(1 x$_)!~/^1?$|^(11+?)\1+$/&&print"$_ "while ++$_'
複製**
另外,讓我們來舉一反三,根據上述的這種方法,我們甚至可以用正規表示式來求證某方式是否有解,如:
大家不妨自己做做練習,為什麼上述的兩個正規表示式可以判斷方程是否有解。如果無法參透其中的奧妙的話,你可以讀讀這篇英文文章。
檢查素數的正規表示式
一般來說,我們會使用正規表示式來做字串匹配,今天在網上瀏覽的時候,看到了有人用正規表示式來檢查乙個數字是否為素數 質數 讓我非常感興趣,這個正規表示式如入所示 檢查素數與否的正規表示式 要使用這個正規則表示式,你需要把自然數轉成多個1的字串,如 2 要寫成 11 3 要寫成 111 17 要寫成 1...
正規表示式 正規表示式 總結
非負整數 d 正整數 0 9 1 9 0 9 非正整數 d 0 負整數 0 9 1 9 0 9 整數 d 非負浮點數 d d 正浮點數 0 9 0 9 1 9 0 9 0 9 1 9 0 9 0 9 0 9 1 9 0 9 非正浮點數 d d 0 0 負浮點數 正浮點數正則式 英文本串 a za z...
奇淫怪巧 利用正規表示式判斷素數
最近在學習正規表示式,偶然間看到利用正規表示式判斷乙個數是不是素數的帖子。當時就震驚了,覺得好神奇。那個判斷素數的函式是這樣子的 public static bool isprime int i 有沒有覺得很神奇?我當時就覺得相當的有想象力的一種實現。那讓我們看一下這個正規表示式是如何做判斷素數的。...