Ответ 1
Вы хотите обрабатывать точку (.
) как запятую (,
). Итак, замените
if (double.TryParse(values[i, j], out tmp))
с
if (double.TryParse(values[i, j].Replace('.', ','), out tmp))
Я пытаюсь написать функцию, которая в основном преобразует массив строк в массив строк, где все удвои в массиве округлены до количества десятичных мест, которые я задал. Также могут быть строки в массиве, которые вообще не являются двойными значениями.
string[,] values = new string[1, 3];
values[0, 0] = "hello";
values[0, 1] = "0.123";
values[0, 2] = "0,123";
int decimalPlaces = 2;
double tmp;
string format = "F" + decimalPlaces.ToString();
IFormatProvider provider = CultureInfo.InvariantCulture;
for (int i = 0; i < values.GetLength(0); i++)
{
for (int j = 0; j < values.GetLength(1); j++)
{
if (double.TryParse(values[i, j], out tmp))
{
values[i, j] = tmp.ToString(format, provider);
}
}
}
Console.ReadLine();
Результат должен быть: "hello", "0.12" , "0.12" , но "hello", "123.00", "0.12" будет обрабатывать запятую неправильно. У кого-нибудь есть простое и эффективное решение для этого?
Вы хотите обрабатывать точку (.
) как запятую (,
). Итак, замените
if (double.TryParse(values[i, j], out tmp))
с
if (double.TryParse(values[i, j].Replace('.', ','), out tmp))
Лечить и то, и другое. как десятичную точку, вы должны не только заменить ее на другую, но также убедиться, что используемый синтаксический анализ Culture интерпретирует ее как десятичную точку.
text = text.Replace(',', '.');
return double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
Вам НЕ НУЖНО заменить запятую и точку..
У меня была та же проблема. Причина проста: культура конверсии играет большую роль в интерпретации запятой или точки. Я использую немецкую культуру, где запятая различает дроби, где, как и везде, точка работает.
Здесь я сделал полный пример, чтобы прояснить разницу.
string[] doubleStrings = {"hello", "0.123", "0,123"};
double localCultreResult;
foreach (var doubleString in doubleStrings)
{
double.TryParse(doubleString, NumberStyles.Any, CultureInfo.CurrentCulture, out localCultreResult);
Console.WriteLine(string.Format("Local culture results for the parsing of {0} is {1}", doubleString, localCultreResult));
}
double invariantCultureResult;
foreach (var doubleString in doubleStrings)
{
double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture, out invariantCultureResult);
Console.WriteLine(string.Format("Invariant culture results for the parsing of {0} is {1}", doubleString, invariantCultureResult));
}
Результаты следующие:
Поиграйте с культурой, и вы получите желаемый результат.
Проблема заключается в том, что вы (или система) не можете отличить десятичный разделитель от разделителя тысяч, когда они могут быть как запятой, так и точкой. Например:
В моей культуре
1.123
- нормальное обозначение для числа выше 1000; в то время как
1,123
- число вблизи 1.
Использование инвариантной культуры по умолчанию использует точку в качестве десятичного разделителя. В общем, вы должны убедиться, что все числа написаны с использованием одной и той же постоянной культуры во всех системах (например, инвариантная культура).
Если вы уверены, что ваши номера никогда не содержат ничего, кроме запятой или точкой для десятичного разделителя (т.е. разделителей тысяч), я бы String.Replace()
запятую с точкой и выполняю остальные так же, как и вы.
В противном случае вам будет сложно программировать что-то, что может отличить 1.123
от 1,123
, не зная культуры.
Создайте две статичные культуры: одну для запятой и одну для точки.
var commaCulture = new CultureInfo("en")
{
NumberFormat =
{
NumberDecimalSeparator = ","
}
};
var pointCulture = new CultureInfo("en")
{
NumberFormat =
{
NumberDecimalSeparator = "."
}
};
Затем используйте каждый соответственно, в зависимости от ввода (используя функцию):
public double ConvertToDouble(string input)
{
input = input.Trim();
if (input == "0") {
return 0;
}
if (input.Contains(",") && input.Split(',').Length == 2)
{
return Convert.ToDouble(input, commaCulture);
}
if (input.Contains(".") && input.Split('.').Length == 2)
{
return Convert.ToDouble(input, pointCulture);
}
throw new Exception("Invalid input!");
}
Затем переберите свои массивы
var strings = new List<string> {"0,12", "0.122", "1,23", "00,0", "0.00", "12.5000", "0.002", "0,001"};
var doubles = new List<double>();
foreach (var value in strings) {
doubles.Add(ConvertToDouble(value));
}
Это должно работать, даже если среда и культура хоста меняются.
Используйте эту перегрузку double.TryParse, чтобы указать разрешенные форматы:
Double.TryParse Method (String, NumberStyles, IFormatProvider, Double%)
По умолчанию double.TryParse будет анализироваться на основе существующих форматов культуры.
Расширение для разбора десятичного числа из строки.
Возможность установки десятичного символа вручную.
public static class StringExtension
{
public static double DoubleParseAdvanced(this string strToParse, char decimalSymbol = ',')
{
string tmp = Regex.Match(strToParse, @"([-]?[0-9]+)([\s])?([0-9]+)?[." + decimalSymbol + "]?([0-9 ]+)?([0-9]+)?").Value;
if (tmp.Length > 0 && strToParse.Contains(tmp))
{
var currDecSeparator = System.Windows.Forms.Application.CurrentCulture.NumberFormat.NumberDecimalSeparator;
tmp = tmp.Replace(".", currDecSeparator).Replace(decimalSymbol.ToString(), currDecSeparator);
return double.Parse(tmp);
}
return 0;
}
}
Как использовать:
"It 4.45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It 4,45 O'clock now".DoubleParseAdvanced(); // will return 4.45
"It 4:45 O'clock now".DoubleParseAdvanced(':'); // will return 4.45
Вы можете проверить, содержит ли строка десятичную точку, используя
string s="";
if (s.Contains(','))
{
//treat as double how you wish
}
а затем рассмотрим это как десятичное значение, иначе просто передайте недвоенное значение.
попробуйте это... он работает для меня.
double vdouble = 0;
string sparam = "2,1";
if ( !Double.TryParse( sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble ) )
{
if ( sparam.IndexOf( '.' ) != -1 )
{
sparam = sparam.Replace( '.', ',' );
}
else
{
sparam = sparam.Replace( ',', '.' );
}
if ( !Double.TryParse( sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble ) )
{
vdouble = 0;
}
}