繁体   English   中英

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

[英]Regular Expression for any number divisible by 60 using C# .Net?

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

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

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

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

谢谢

为什么不做N % 60

为什么要将regex用于可以使用一个运算符轻松完成的工作?

正如其他人所提到的,正则表达式完全是错误的工具 相反,使用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)$

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

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

这是一个正则表达式,用于测试数字是否可被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应用程序中的客户端验证。
  • 它不允许带前导零的数字(如果你想允许前导零只删除(?!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 ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM