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

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

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

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

希望有人能解决我的问题。

谢谢

正则表达式中的(+,/, – ,*)不用作数学运算符。 请改用JavaScript。

为什么不做N % 60

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

正如其他人所提到的,正则表达式完全是错误的工具 。 相反,使用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整除的十进制数吗? 如果可以,让我们看看吧。 如果没有,你能提供一个没有这种正则表达式的证据吗? (也就是说,我所描述的语言并不规律。)

我想出了这个:

^((?=[^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)$

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

这是一个正则表达式,用于测试数字是否可被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.它与tiftik发布的正则表达式有以下几种不同:

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

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

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