#c# #parsing #floating-point
#c# #синтаксический анализ #значение с плавающей запятой
Вопрос:
Я считываю числа из XML-файлов. Другие числа разделяются запятой (0,1111), а другие — точкой (0,111). Как мне проанализировать эти числа, чтобы в итоге получить желаемый результат? Я пытался использовать float.Parse(reader.Value, System.Globalization.CultureInfo.InvariantCulture);
, но это не работает. Например, у меня есть reader.Значение = «0,01119703» и анализируется как 1119703.0.
Комментарии:
1. Как вы хотите, чтобы это было проанализировано?
2. Кто предоставляет вам такие странные данные? Похоже, настоящая проблема связана с исходным кодом…
3. @soandos Я хочу, чтобы оно анализировалось как число с плавающей точкой. Изначально это строка.
4. @Cameron, не все локали используют . в качестве их десятичного разделителя, таким образом, если бы это было приложение, в котором вы могли получать числа, например, из en-US и fr-CA, вы могли бы получить . или , соответственно. Для получения дополнительной информации … en.wikipedia.org/wiki/Decimal_mark
5. @Cameron Возможно, но я не могу изменить источник
Ответ №1:
Я не верю, что возможно работать с двумя разными десятичными разделителями одновременно. Я думаю, я бы просто использовал Replace (), чтобы заменить любые запятые на точки.
float.Parse(reader.Value.Replace(',', '.'), System.Globalization.CultureInfo.InvariantCulture);
Комментарии:
1. Единственным риском при таком подходе было бы, если бы числа могли когда-либо быть в формате 1,000.00
2. Это немного запутанно. Если я введу «3,456.78», приведенный выше код изменит его на «3.456.78», что, вероятно, приведет к ошибке синтаксического анализа.
3. Это не вариант. Я не могу ничего изменить в исходном коде.
4. Я не говорю об изменении xml-файла, просто меняю код, чтобы вы заменили любые запятые точками, прежде чем передавать их в float . Синтаксический анализ(). Как указывали другие, это приведет к сбою, если могут быть тысячи разделителей. В этом случае вам, вероятно, пришлось бы использовать регулярное выражение.
Ответ №2:
Не уверен, что это лучшее решение, но, возможно, вы могли бы положиться на набор известных «пользовательских» числовых форматов. Например, вы могли бы объявить два пользовательских числовых формата (либо с нуля, либо на основе известного формата), таких как:
private static readonly NumberFormatInfo DecimalSeparatorFormat = new NumberFormatInfo { NumberDecimalSeparator = ".", NumberGroupSeparator = "," };
private static readonly NumberFormatInfo CommaSeparatorFormat = new NumberFormatInfo { NumberDecimalSeparator = ",", NumberGroupSeparator = "." };
А затем попробуйте проанализировать число с помощью известных вам принятых форматов:
if (!Single.TryParse(unparsedValue, NumberStyles.Float, DecimalSeparatorFormat, out parsedValue) amp;amp; !Single.TryParse(unparsedValue, NumberStyles.Float, CommaSeparatorFormat, out parsedValue))
throw new FormatException("Number format not supported");
Это предполагает, что у вас есть конечное число известных форматов, если ваши входные данные действительно могут быть в любой культуре, тогда вам может не повезти с поиском отличного решения.
Единственный выигрыш при таком подходе заключается в том, что вы, по крайней мере, четко указываете форматы, которые можете поддерживать, а не полагаетесь на простую замену строки (что может привести к недопустимому формату).
Ответ №3:
Есть ли что-нибудь в XML-файлах, что подскажет вам, какой формат используется? В .NET нет встроенного способа иметь два разных разрешенных десятичных разделителя. Если ничто не указывает вам, в каком формате будет число, то вы всегда можете проверить, содержит ли строка точку или запятую, и создать NumberFormatInfo с этим в качестве десятичного разделителя. Конечно, это не сработает, если какое-либо из чисел имеет точку или запятую в качестве разделителя тысяч.
Комментарии:
1. Это небольшие числа, поэтому, вероятно, нет никакого разделителя тысяч. Как мне проверить, является ли это запятой или точкой? Должен ли я проверять строку, содержит ли она эти символы?
2. Вам не нужно ничего проверять, просто используйте функцию Replace(). Если он не находит символ для замены, он возвращает исходную строку. Смотрите код, который я опубликовал в своем ответе 🙂