it-swarm.com.de

Regulärer Ausdruck für Dezimalzahl

Ich muss eine textbox-Eingabe validieren und kann nur Dezimaleingaben zulassen wie: X,XXX (nur eine Ziffer vor dem Dezimalzeichen und eine Genauigkeit von 3).

Ich verwende C # und versuche diese ^[0-9]+(\.[0-9]{1,2})?$?

30
davorn
^[0-9]([.,][0-9]{1,3})?$

Es erlaubt:

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

ABER NICHT:

.1
,1
12.1
12,1
1.
1,
1.2345
1,2345
54
J-16 SDiZ

Es gibt einen alternativen Ansatz, bei dem es keine I18n-Probleme gibt (Erlaube ',' oder '.', Aber nicht beide): Decimal.TryParse .

Versuchen Sie einfach zu konvertieren und ignorieren Sie den Wert.

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

Dies ist wesentlich schneller als bei Verwendung eines regulären Ausdrucks (siehe unten).

(Die Überladung von Decimal.TryParse kann zur feineren Steuerung verwendet werden.)


Leistungstestergebnisse: Decimal.TryParse: 0.10277ms, Regex: 0.49143ms

Code (PerformanceHelper.Run ist ein Helfer, der den Delegaten für den übergebenen Iterationszähler ausführt und den Durchschnitt TimeSpan zurückgibt.):

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);
    }
}
19
Richard
\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

Streichhölzer:
1
1.2
1.23
1.234

8
UnkwnTech

Im Allgemeinen, d. H. Unbegrenzte Dezimalstellen:

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

4
SK9

Ich habe gerade festgestellt, dass TryParse() ein Problem hat, das Tausende von Separatoren berücksichtigt. Beispiel in En-US ist 10.36.00 in Ordnung. Ich hatte ein spezifisches Szenario, in dem der Tausendertrenner nicht berücksichtigt werden sollte, und daher erwies sich Regex \d(\.\d) als die beste Wahl. Natürlich musste die dezimale Zeichenvariable für verschiedene Ländereinstellungen beibehalten werden.

1
Rajesh

Während ich mich damit auseinandersetzte, hat TryParse in 3.5 NumberStyles: Der folgende Code sollte auch den Trick tun, ohne dass Regex Tausende von Separatoren ignoriert.

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

Nicht relevant für die ursprüngliche Frage, aber Bestätigung, dass TryParse () tatsächlich eine gute Option ist.

0
rvanchis

In .NET empfehle ich, den regulären Ausdruck mit dem Dezimaltrennzeichen des aktuellen kulturellen Kontexts dynamisch zu erstellen:

using System.Globalization;

...

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

Möglicherweise möchten Sie den regulären Ausdruck verstärken, indem Sie 1000er-Trennzeichen auf dieselbe Weise zulassen wie das Dezimalzeichen.

0
thomiel