簡體   English   中英

十進制數的正則表達式

[英]Regular expression for decimal number

我需要驗證textbox輸入,並且只能允許十進制輸入,如: X,XXX (十進制符號前只有一位數,精度為3)。

我正在使用C#並試試這個^[0-9]+(\\.[0-9]{1,2})?$

^[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

有一種替代方法,它沒有I18n問題(允許','或'。'而不是兩者): Decimal.TryParse

試試轉換,忽略價值。

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

這比使用正則表達式快得多,見下文。

Decimal.TryParse的重載可用於更精細的控制。)


性能測試結果:Decimal.TryParse:0.10277ms,正則表達式: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: {0}ms, Regex: {1}ms",
                              parserTime.TotalMilliseconds, 
                              regexTime.TotalMilliseconds,
                              run);
            paserTotal += parserTime.TotalMilliseconds;
            regexTotal += regexTime.TotalMilliseconds;
        }

        Console.WriteLine("Overall averages: Decimal.TryParse: {0}ms, Regex: {1}ms",
                          paserTotal/runCount,
                          regexTotal/runCount);
    }
}
\d{1}(\.\d{1,3})?

Match a single digit 0..9 «\d{1}»
   Exactly 1 times «{1}»
Match the regular expression below and capture its match into backreference number 1 «(\.\d{1,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 «\d{1,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-9]\\d*)|0)(.0*[1-9](0*[1-9])*)?$

我剛發現TryParse()有一個問題,它占了數千個分隔符。 En-US中的示例,10,36.00即可。 我有一個特定的場景,不應該考慮成千上萬的分隔符,因此正則表達式\\d(\\.\\d)被證明是最好的選擇。 當然必須為不同的語言環境保留decimal char變量。

在.NET中,我建議使用當前文化上下文的小數分隔符動態構建正則表達式:

using System.Globalization;

...

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

您可能希望通過允許1000er分隔符與小數分隔符相同的方式來對正則表達式進行操作。

正如我爭論的那樣,3.5中的TryParse確實有NumberStyles:下面的代碼也應該沒有正則表達式來忽略數千個分隔符。

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

與原始問題無關,但確認TryParse()確實是一個不錯的選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM