zoukankan      html  css  js  c++  java
  • [奇淫怪巧] 利用正则表达式判断素数

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

    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了。对于素数的效率是一样的,因为每个位置都需要匹配过来,但是对于非素数从小开始匹配则能够让这个表达式早点结束匹配。

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

  • 相关阅读:
    HDU 1025 Constructing Roads In JGShining's Kingdom (DP+二分)
    HDU 1158 Employment Planning
    HDU 2059 龟兔赛跑
    Csharp 简单操作Word模板文件
    Csharp windowform datagridview Clipboard TO EXCEL OR FROM EXCEL DATA 保存datagridview所有數據
    Csharp 讀寫文件內容搜索自動彈出 AutoCompleteMode
    Csharp windowform controls clear
    CSS DIV大图片右上角叠加小图片
    Csharp DataGridView自定义添加DateTimePicker控件日期列
    Csharp 打印Word文件默認打印機或選擇打印機設置代碼
  • 原文地址:https://www.cnblogs.com/imjustice/p/check_prime_by_using_regular_expression.html
Copyright © 2011-2022 走看看