В среде, которую моя программа собирается выполнить, люди используют'', и'.' в качестве десятичных разделителей случайным образом на ПК с'' и'.' разделителей.
Как был бы Вы реализовывать такой floatparse (строка) функция?
Я попробовал этого:
try
{
d = float.Parse(s);
}
catch
{
try
{
d = float.Parse(s.Replace(".", ","));
}
catch
{
d = float.Parse(s.Replace(",", "."));
}
}
Это не работает. И когда я отлаживаю, оказывается, что это анализирует его, неправильно в первый раз думая, что это - разделитель для тысяч (как 100.000.000,0).
Я - новичок в C#, так надо надеяться, существует менее сверхсложное решение затем это :-)
Люди NB: попытка использовать обоих '.' и'', в ПК с различными настройками разделителя.
Если вы уверены, что никто не использует разделители разрядов, вы можете сначала заменить:
string s = "1,23"; // or s = "1.23";
s = s.Replace(',', '.');
double d = double.Parse(s, CultureInfo.InvariantCulture);
Общий шаблон будет следующим:
Я бы сделал что-то вроде этого
float ConvertToFloat(string value)
{
float result;
var converted = float.TryParse(value, out result);
if (converted) return result;
converted = float.TryParse(value.Replace(".", ",")),
out result);
if (converted) return result;
return float.NaN;
}
В этом случае следующее вернет правильные данные
Console.WriteLine(ConvertToFloat("10.10").ToString());
Console.WriteLine(ConvertToFloat("11,0").ToString());
Console.WriteLine(ConvertToFloat("12").ToString());
Console.WriteLine(ConvertToFloat("1 . 10").ToString());
Returns
10,1
11
12
NaN
В этом случае, если не получится преобразовать, вы хотя бы будете знать, что это не число. Это безопасный способ преобразования.
Вы также можете использовать следующую перегрузку
float.TryParse(value,
NumberStyles.Currency,
CultureInfo.CurrentCulture,
out result)
На этом тестовом коде:
Console.WriteLine(ConvertToFloat("10,10").ToString());
Console.WriteLine(ConvertToFloat("11,0").ToString());
Console.WriteLine(ConvertToFloat("12").ToString());
Console.WriteLine(ConvertToFloat("1 . 10").ToString());
Console.WriteLine(ConvertToFloat("100.000,1").ToString());
Он возвращает следующее
10,1
11
12
110
100000,1
Итак, в зависимости от того, насколько "милым" вы хотите быть для пользователя, вы всегда можете заменить последний шаг, если это не число, попробуйте преобразовать его таким образом, иначе это действительно не число.
Это будет выглядеть следующим образом
float ConvertToFloat(string value)
{
float result;
var converted = float.TryParse(value,
out result);
if (converted) return result;
converted = float.TryParse(value.Replace(".", ","),
out result);
if (converted) return result;
converted = float.TryParse(value,
NumberStyles.Currency,
CultureInfo.CurrentCulture,
out result);
return converted ? result : float.NaN;
}
Где следующее
Console.WriteLine(ConvertToFloat("10,10").ToString());
Console.WriteLine(ConvertToFloat("11,0").ToString());
Console.WriteLine(ConvertToFloat("12").ToString());
Console.WriteLine(ConvertToFloat("1 . 10").ToString());
Console.WriteLine(ConvertToFloat("100.000,1").ToString());
Console.WriteLine(ConvertToFloat("asdf").ToString());
Возвращает
10,1
11
12
110
100000,1
NaN
Парсинг использует настройки CultureInfo.CurrentCulture, которые отражают язык и формат чисел, выбранный пользователем через Regional Settings. Если ваши пользователи вводят десятичные числа, соответствующие языку, который они выбрали для своих компьютеров, у вас не должно возникнуть проблем с использованием старого доброго double.Parse(). Если пользователь установит свою локаль на греческий язык и наберет "8,5", double.Parse("8,5") вернет 8,5. Если он напечатает "8,5", разбор вернет 85.
Если пользователь устанавливает одну локаль, а затем начинает использовать неправильную десятичную дробь, вы сталкиваетесь с проблемой. Не существует чистого способа отделить такие неправильные записи от записей, которые действительно хотели ввести группирующий символ. Что вы можете сделать, так это предупредить пользователя, когда число слишком короткое, чтобы включить символ группировки, и использовать маски или числовые текстовые поля для предотвращения неправильного ввода.
Другой, несколько более жесткий вариант - запретить группирующий символ для ввода чисел в вашем приложении, отменив его в событии KeyDown ваших текстовых полей. Вы можете получить числовые и группирующие символы из свойства CultureInfo.CurrentCulture.NumberFormat.
Попытка заменить десятичные и группирующие символы обречена на неудачу, поскольку она зависит от знания во время компиляции, какой тип разделителя будет использовать пользователь. Если бы вы знали это, вы могли бы просто разобрать число, используя CultureInfo в сознании пользователя. К сожалению, User.Brain.CultureInfo пока не является частью .NET framework :P