Проверять число с плавающей запятой, используя RegEx в С#
Я пытаюсь сделать только числовое число TextBox
в WPF, и у меня есть для него этот код:
void NumericTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !IsValidInput(e.Text);
}
private bool IsValidInput(string p)
{
switch (this.Type)
{
case NumericTextBoxType.Float:
return Regex.Match(p, "^[0-9]*[.][0-9]*$").Success;
case NumericTextBoxType.Integer:
default:
return Regex.Match(p, "^[0-9]*$").Success;
}
}
// And also this!
public enum NumericTextBoxType
{
Integer = 0,
Float = 1
}
Когда я устанавливаю тип Integer, он работает хорошо, но для Float это не так.
Я могу использовать так много элементов управления NumericTextBox
, но мне было интересно, почему этот не работает?
Ответы
Ответ 1
Попробуйте следующее:
@"^[0-9]*(?:\.[0-9]*)?$"
Вам нужно избежать периода. И сделать необязательную опцию периода и десятичной длины, вероятно, хорошей идеей.
Если вам нужно обрабатывать отрицательные значения, вы можете добавить -?
до первого [0-9]
в каждом шаблоне.
Обновление
Протестировано следующим образом:
var regex = new Regex(@"^[0-9]*(?:\.[0-9]*)?$");
Console.WriteLine(new bool[] {regex.IsMatch("blah"),
regex.IsMatch("12"),
regex.IsMatch(".3"),
regex.IsMatch("12.3"),
regex.IsMatch("12.3.4")});
приводит к
False
True
True
True
False
Ответ 2
Я настоятельно рекомендую использовать метод Double.TryParse() вместо проверки регулярных выражений. Используя TryParse()
, ваше приложение будет немного более универсальным с точки зрения культуры. Когда текущая культура изменяется, TryParse()
будет анализироваться без проблем. Также методы TryParse()
, которые, как полагают, не имеют ошибок, поскольку они были протестированы сообществом .net:).
Но в случае регулярного выражения вы должны изменить свое выражение проверки, следовательно, оно не может иметь никакого отношения к новой культуре.
Вы можете переписать код следующим образом:
private bool IsValidInput(string p)
{
switch (this.Type)
{
case NumericTextBoxType.Float:
double doubleResult;
return double.TryParse(p, out doubleResult);
case NumericTextBoxType.Integer:
default:
int intResult;
return int.TryParse(p, out intResult);
}
}
Вы даже можете добавить свои собственные методы расширения, чтобы сделать парсинг более элегантным.
public static double? TryParseInt(this string source)
{
double result;
return double.TryParse(source, out result) ? result : (double?)null;
}
// usage
bool ok = source.TryParseInt().HasValue;
Ответ 3
Проверьте статические методы TryParse
, которые вы найдете в double, float и int.
Они возвращают true, если строка может быть проанализирована (методом Parse
).
Ответ 4
[-+]?\d+(.\d+)?
Самое простое регулярное выражение для float. Это не соответствует случаям "123." или '.123'.
Кроме того, вы должны посмотреть на контекстную культуру:
CultureInfo ci = CultureInfo.CurrentCulture;
var decimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
var floatRegex = string.Format(@"[-+]?\d+({0}\d+)?", decimalSeparator);
Ответ 5
Я попробовал решение, одобренное выше, обнаружил, что он не сработает, если пользователь вводит только точку
@"^[0-9]*(?:\.[0-9]*)?$"
.
Итак, я изменил его на:
@"^[0-9]*(?:\.[0-9]+)?$"
Ответ 6
Это код, который я придумал, смешивая ответы от @Andrew Cooper и @Ramesh. Добавлен код словаря, поэтому любое тело, думающее о тестировании кода, может запускать как можно больше тестовых примеров.
//greater than or equal to zero floating point numbers
Regex floating = new Regex(@"^[0-9]*(?:\.[0-9]+)?$");
Dictionary<string, bool> test_cases = new Dictionary<string, bool>();
test_cases.Add("a", floating.IsMatch("a"));
test_cases.Add("a.3", floating.IsMatch("a.3"));
test_cases.Add("0", floating.IsMatch("0"));
test_cases.Add("-0", floating.IsMatch("-0"));
test_cases.Add("-1", floating.IsMatch("-1"));
test_cases.Add("0.1", floating.IsMatch("0.1"));
test_cases.Add("0.ab", floating.IsMatch("0.ab"));
test_cases.Add("12", floating.IsMatch("12"));
test_cases.Add(".3", floating.IsMatch(".3"));
test_cases.Add("12.3", floating.IsMatch("12.3"));
test_cases.Add("12.3.4", floating.IsMatch("12.3.4"));
test_cases.Add(".", floating.IsMatch("."));
test_cases.Add("0.3", floating.IsMatch("0.3"));
test_cases.Add("12.31252563", floating.IsMatch("12.31252563"));
test_cases.Add("-12.31252563", floating.IsMatch("-12.31252563"));
foreach (KeyValuePair<string, bool> pair in test_cases)
{
Console.WriteLine(pair.Key.ToString() + " - " + pair.Value);
}