使用C#.Net可以被60整除的任何数字的正则表达式?

时间:2010-03-12 04:45:31

标签: c# .net asp.net regex

我需要对以秒为单位的输入时间间隔应用验证。现在我并不擅长正则表达式。所以任何身体都可以帮助制作一个正则表达式,可以测试一个数字是否可被60整除。

我想知道我是否可以用来测试一个检查该数字是否可被10整除,然后检查它是否可以被6整除。

对于可被10整除的数字,这里[\ d * 0]是我猜的表达式。如果我错了,请纠正我。

希望有人解决我的问题。

由于

6 个答案:

答案 0 :(得分:17)

为什么不N % 60

为什么要使用正则表达式来完成一个可以使用一个操作符轻松完成的工作?

答案 1 :(得分:15)

正如其他人所提到的,正则表达式完全是用于此的错误工具。相反,使用TryParse将字符串转换为整数,然后测试整数是否可被60整除。

也就是说,看看这有可能与正则表达式一起工作是有益的。

首先,在一位数的数字中,只有0可被60整除。在非一位数字中,所有可被60整除的数字也可被20整除,因此以00,20,40结束,60或80.这很容易用正则表达式测试。

假设它通过了第一次测试。我们从这个测试中知道这个数字可以被20整除。现在我们需要做的就是表明它可以被3整除。如果是,那么它可以被20和3整除,因此必须可被60整除,因为20和3是互质的。

因此我们需要一个正则表达式来确定一个数字是否可以被3整除。

众所周知,可被3整除的数字使得它们的数字之和可以被3整除。

众所周知,每个正则表达式对应一个有限状态机,每个有限状态机对应一个正则表达式。

因此,如果我们能够提出一个有限状态机来确定可分性为三,我们就完成了。

这很容易做到。我们的有限状态机有三种状态,A,B和C.起始状态是A.接受状态是A.转换是:

当处于状态A时,输入0,3,6和9进入状态A.输入1,4和7进入状态B.输入2,5和8进入状态C.

当处于状态B时,输入0,3,6和9进入状态B.输入1,4和7进入状态C.输入2,5和8进入状态A.

当处于状态C时,输入0,3,6和9进入状态C.输入1,4和7进入状态A.输入2,5和8进入状态B.

所有其他输入都进入错误状态。

我们已经完成了;我们有一个有限的状态机,它检查可分性为3.因此我们可以构建一个regexp来检查3的可分性;如果我们将检查可消除性的正则表达式与20结合起来,那么我们就有了所需的正则表达式。 以十进制表示法编写的数字语言可被60整除,是一种常规语言。

这种正则表达式的实际构造留作练习。 (看起来这就是tiftik所做的。)

练习:你能想出一个正则表达式来判断字符串是否包含一个可被70整除的十进制数吗?如果可以,让我们看看。如果没有,你能否提供不存在这种正则表达式的证据? (也就是说,我所描述的语言并不规律。)

答案 2 :(得分:8)

我想出了这个:

^((?=[^147]*(([147][^147]*){3})*$)(?=[^258]*(([258][^258]*){3})*$)|(?=[^147]*(([147][^147]*){3})*[147][^147]*$)(?=[^258]*(([258][^258]*){3})*[258][^258]*$)|(?=[^147]*(([147][^147]*){3})*([147][^147]*){2}$)(?=[^258]*(([258][^258]*){3})*([258][^258]*){2}$))\d*0(?<=[02468][048]|[13579][26]|^0)$

注意:为简单起见,我没有使用非捕获组。

编辑:缩短版本:

^(?=[^147]*(?:(?:[147][^147]*){3})*(?:()|([147][^147]*)|((?:[147][^147]*){2}))$)(?=[^258]*(?:(?:[258][^258]*){3})*(?:()|([258][^258]*)|((?:[258][^258]*){2}))$)((?(1)(?(4)|.$)|.$)|(?(2)(?(5)|.$)|.$)|(?(3)(?(6)|.$)|.$))\w*0(?<=[02468]0|^0)$

答案 3 :(得分:6)

正则表达式中的

(+,/, - ,*)不用作数学运算符。请改用JavaScript。

答案 4 :(得分:4)

注意:正则表达式不是正确的工具。这只是为了好玩,看看它是如何完成的。

这是一个正则表达式,用于测试数字是否可被60整除:

^0$|^(?!0)(?=.*[02468]0$)(?:[0369]|[147](?:[0369]*[147][0369]*[258])*(?:[0369]*[258]|[0369]*[147][0369]*[147])|[258](?:[0369]*[258][0369]*[147])*(?:[0369]*[147]|[0369]*[258][0369]*[258]))*0$

它的工作原理是测试数字是否可被3整除并使用前瞻来检查它是否可以除以20.它与regular expression posted by tiftik的区别在于以下几种方式:

  • 略短。
  • 它使用非捕获组。
  • 许多语言(例如Javascript)不支持可变长度的lookbehind断言。此正则表达式不使用lookbehinds,因此它也可以用于Web应用程序中的客户端验证。
  • 它不允许带前导零的数字(如果你想允许前导零只删除(?!0))。

这是我用来生成和测试它的代码:

using System;
using System.Text;
using System.Text.RegularExpressions;

class Program
{
    Regex createRegex()
    {
        string a = "[0369]*";
        string b = "a[147]";
        string c = "a[258]";
        string r = "^0$|^(?!0)(?=.*[02468]0$)(?:[0369]|[147](?:bc)*(?:c|bb)|[258](?:cb)*(?:b|cc))*0$";
        r = r.Replace("b", b).Replace("c", c).Replace("a", a);
        return new Regex(r);
    }

    bool isDivisibleBy3(string s)
    {
        int sumOfDigits = 0;
        foreach (char c in s)
        {
            sumOfDigits += c - '0';
        }
        return sumOfDigits % 3 == 0;
    }

    bool isDivisibleBy20(string s)
    {
        return Regex.IsMatch(s, "^0$|[02468]0$");
    }

    bool isDivisibleBy60(string s)
    {
        return isDivisibleBy3(s) && isDivisibleBy20(s);
    }

    bool isValid(string s)
    {
        return Regex.IsMatch(s, "^0$|^[1-9][0-9]*$");
    }

    void Run()
    {
        Regex regex = createRegex();
        Console.WriteLine(regex);

        // Test on some random strings.
        Random random = new Random();
        for (int i = 0; i < 100000; ++i)
        {
            int length = random.Next(50);
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < length; ++j)
            {
                sb.Append(random.Next(10));
            }
            string s = sb.ToString();
            bool isMatch = regex.IsMatch(s);
            bool expected = isValid(s) && isDivisibleBy60(s);
            if (isMatch != expected)
            {
                Console.WriteLine("Failed for " + s);
            }
        }
    }

    static void Main()
    {
        new Program().Run();
    }
}

答案 5 :(得分:2)

正则表达式是这项工作的错误工具。相反,尝试除以60并查看是否没有余数:

if (value % 60 == 0) {
  // is divisible by 60
  // ... do something ...
}