十进制数的正则表达式

Posted

技术标签:

【中文标题】十进制数的正则表达式【英文标题】:Regular expression for decimal number 【发布时间】:2010-11-01 09:56:55 【问题描述】:

我需要验证 textbox 输入并且只能允许十进制输入,例如:X,XXX(小数符号前只有一位,精度为 3)。

我正在使用 C# 并试试这个 ^[0-9]+(\.[0-9]1,2)?$?

【问题讨论】:

为什么要在这里使用正则表达式而不是框架解决方案(decimal.TryParse)? 【参考方案1】:
^[0-9]([.,][0-9]1,3)?$

它允许:

0
1
1.2
1.02
1.003
1.030
1,2
1,23
1,234

但不是:

.1
,1
12.1
12,1
1.
1,
1.2345
1,2345

【讨论】:

用 \d 替换 [0-9] 会减少 3 个字符(总共 6 个)并执行相同的操作。 +1 但接受 0.1 不是很好吗,因为这是 0.1 的有效表示(使用 Decimal.Parse 测试)? 最简单的版本是 "\d(\.\d1,3)?"但使用“\d(?:\.\d1,3)?”将意味着不存储组。 这仅在用户的区域设置使用 .作为小数分隔符。如果它是 ,(例如,在 fr-FR 中......),它将中断。 允许“1”。和 '1,' 我已将正则表达式更改为 ^[0-9]1([\.\,]|([\.\,][0-9]1,3))?$ 【参考方案2】:

还有一种替代方法,它没有 I18n 问题(允许使用 ',' 或 '.' 但不能同时使用):Decimal.TryParse

只是尝试转换,忽略值。

bool IsDecimalFormat(string input) 
  Decimal dummy;
  return Decimal.TryParse(input, out dummy);

这比使用正则表达式要快得多,见下文。

Decimal.TryParse的重载可用于更精细的控制。)


性能测试结果:Decimal.TryParse:0.10277ms,Regex:0.49143ms

代码(PerformanceHelper.Run 是一个助手,它运行委托以获取传递的迭代计数并返回平均值 TimeSpan。):

using System;
using System.Text.RegularExpressions;
using DotNetUtils.Diagnostics;

class Program 
    static private readonly string[] TestData = new string[] 
        "10.0",
        "10,0",
        "0.1",
        ".1",
        "Snafu",
        new string('x', 10000),
        new string('2', 10000),
        new string('0', 10000)
    ;

    static void Main(string[] args) 
        Action parser = () => 
            int n = TestData.Length;
            int count = 0;
            for (int i = 0; i < n; ++i) 
                decimal dummy;
                count += Decimal.TryParse(TestData[i], out dummy) ? 1 : 0;
            
        ;
        Regex decimalRegex = new Regex(@"^[0-9]([\.\,][0-9]1,3)?$");
        Action regex = () => 
            int n = TestData.Length;
            int count = 0;
            for (int i = 0; i < n; ++i) 
                count += decimalRegex.IsMatch(TestData[i]) ? 1 : 0;
            
        ;

        var paserTotal = 0.0;
        var regexTotal = 0.0;
        var runCount = 10;
        for (int run = 1; run <= runCount; ++run) 
            var parserTime = PerformanceHelper.Run(10000, parser);
            var regexTime = PerformanceHelper.Run(10000, regex);

            Console.WriteLine("Run #2: Decimal.TryParse: 0ms, Regex: 1ms",
                              parserTime.TotalMilliseconds, 
                              regexTime.TotalMilliseconds,
                              run);
            paserTotal += parserTime.TotalMilliseconds;
            regexTotal += regexTime.TotalMilliseconds;
        

        Console.WriteLine("Overall averages: Decimal.TryParse: 0ms, Regex: 1ms",
                          paserTotal/runCount,
                          regexTotal/runCount);
    

【讨论】:

这样不仅更快,而且更干净。 很好的解决方案!【参考方案3】:
\d1(\.\d1,3)?

Match a single digit 0..9 «\d1»
   Exactly 1 times «1»
Match the regular expression below and capture its match into backreference number 1 «(\.\d1,3)?»
   Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
   Match the character “.” literally «\.»
   Match a single digit 0..9 «\d1,3»
      Between one and 3 times, as many times as possible, giving back as needed (greedy) «1,3»


Created with RegexBuddy

比赛: 1 1.2 1.23 1.234

【讨论】:

您甚至可以省略 1 你仍然有 \d1 而不是 \d【参考方案4】:

一般来说,即无限位小数:

^-?(([1-9]\d*)|0)(.0*[1-9](0*[1-9])*)?$

【讨论】:

【参考方案5】:

我刚刚发现TryParse() 有一个问题,它占数千个分隔符。 En-US 中的示例,10,36.00 是可以的。我有一个特定的场景,不应该考虑千位分隔符,因此正则表达式 \d(\.\d) 原来是最好的选择。当然必须为不同的语言环境保留十进制字符变量。

【讨论】:

使用带有NumerStyles参数的Decimal.TryParse的重载,并且不要包含NumerStyles.AllowThousands【参考方案6】:

在 .NET 中,我建议使用当前文化上下文的小数分隔符动态构建正则表达式:

using System.Globalization;

...

NumberFormatInfo nfi = NumberFormatInfo.CurrentInfo;
Regex re = new Regex("^(?\\d+(" 
                   + Regex.Escape(nfi.CurrencyDecimalSeparator) 
                   + "\\d1,2))$");

您可能希望通过允许 1000er 分隔符与小数分隔符相同的方式来对正则表达式进行拉皮条。

【讨论】:

【参考方案7】:

当我对此争论不休时,3.5 中的 TryParse 确实有 NumberStyles:以下代码也应该在没有 Regex 的情况下忽略千位分隔符。

double.TryParse(length, NumberStyles.AllowDecimalPoint,CultureInfo.CurrentUICulture, out lengthD))

与最初提出的问题无关,但确认 TryParse() 确实是一个不错的选择。

【讨论】:

以上是关于十进制数的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

非零和非十进制数的 JQuery 正则表达式验证

0 到 10 范围内任何正或负十进制数的正则表达式

十进制数的正则表达式(最多 3 个带逗号的十进制数)

使用 PCRE 正则表达式匹配两个二进制数的正确加法

具有数字长度限制的数字的正则表达式,包括小数[关闭]

Java判断是不是是整数,小数或实数的正则表达式