#c# #parsing #decimal
#c# #синтаксический анализ #десятичная
Вопрос:
Как преобразовать строку в десятичную, чтобы она работала для обоих форматов — с запятыми и точками?
[Fact]
public void foo(){
var a="1,1";
var b="1.1";
Assert.Equal(Parse(a),Parse(b));
}
private decimal Parse(string s){
return decimal.Parse(s,NumberStyles.Any,
CultureInfo.InvariantCulture);
}
вывод:
Test 'Unit.Sandbox.foo' failed: Assert.Equal() Failure
Expected: 11
Actual: 1,1
Комментарии:
1. Даже если она будет проанализирована, почему они должны быть равны? Один равен 1 точке 1, другой равен одиннадцати …? (поскольку вы явно указываете инвариантную культуру)
2. @Marc Gravell Я не уверен, что правильно вас понял. В любом случае — цель состоит в том, чтобы написать функцию синтаксического анализа, чтобы она понимала оба формата. Утверждение отражает то, чего я пытаюсь достичь.
3. @Arnis: Я полагаю, Марк имел в виду неоднозначность поддержки как десятичной точки, так и разделителя тысяч с использованием разных культур. Но я полагаю, что вас интересует только разбор десятичных точек?
4. @Arnis — Я понимаю , но: оба являются допустимыми числами как в языке «.=point», так и в языке «,=point». Как вы предлагаете понять, что предназначено? В «1,1» вы, возможно, могли бы подделать это, но как насчет «1,001» против «1,001»? Это одно и то же? Независимо от того, используете ли вы или . в качестве «точки», единица равна тысяче и одному, а другая равна одной точке ноль ноль один.
5. @Marc напоминает мне сообщение Джона в блоге «Humanity fail» bit.ly/kQUJcR T_T
Ответ №1:
Вы могли бы попробовать это:
private decimal Parse(string s){
s = s.Replace(",", CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator);
return decimal.Parse(s,NumberStyles.Any,
CultureInfo.InvariantCulture);
}
Комментарии:
1. Если OP хочет поддерживать тысячи символов-разделителей, то это не сработает.
2. @Groo, действительно, но я не вижу, как он мог бы поддерживать разделитель тысяч, если и запятая, и точка должны обрабатываться одинаково…
3. @Thomas это невозможно … 🙁
4. @Arnis L., что невозможно?
5. @Arnis L., это сработает, если вы решите не использовать разделитель тысяч
Ответ №2:
Как насчет этого?
private static decimal Parse(string s)
{
s = s.Replace(",", ".");
return decimal.Parse(s);
}
Комментарии:
1. попробуйте сами: 1.000.000, 25 и 1000000.25
Ответ №3:
Вы должны получить желаемый результат, изменив разделитель десятичной валюты на запятую перед разбором десятичной строки через запятую. Здесь есть несколько полезных ресурсов:
В качестве альтернативы вы могли бы реализовать свой собственный Iformatprovider, как обсуждалось здесь:
http://msdn.microsoft.com/en-us/library/t7xswkc6.aspx http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.aspx
О, или вы могли бы сделать грязный взлом и просто выполнить замену строки на «,» на «.» 😉
Ответ №4:
Если у вас англоязычная операционная система, этот метод преобразует десятичное число с запятой в точку. Если вы владеете русским языком, метод преобразует десятичное число с точкой в запятую.
Console.Write("Input number: ");
string? input = Console.ReadLine();
decimal number = ConvertNumberToCurrentLocale(input);
Console.WriteLine("Result: " number);
decimal ConvertNumberToCurrentLocale(string? input)
{
string separator = Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
switch (separator)
{
case ".":
input = input?.Replace(",", ".");
break;
case ",":
input = input?.Replace(".", ",");
break;
}
decimal.TryParse(input, out var number);
return number;
}