По моему опыту, replaceAll (), как вы предложили, является лучшим способом сделать это. Это не зависит от текущей локали, это просто и работает.
Joonas Pulakka
1
@Marco Altieri: replaceAll(",",".")заменяет все запятые на точки. Если запятых нет, то ничего не происходит. Double.valueOf()работает (только) со строками, которые используют точку в качестве десятичного разделителя. Ничто здесь не зависит от текущей локали по умолчанию. docs.oracle.com/javase/8/docs/api/java/lang/…
Joonas Pulakka
4
Единственная проблема в replaceAll(",",".")том, что он будет работать только при наличии единственной запятой: то есть: 1 234 567 выбрасывает java.lang.NumberFormatException: multiple points. Будет достаточно регулярного выражения с положительным взглядомp.replaceAll(",(?=[0-9]+,)", "").replaceAll(",", ".") Подробнее на: регулярно-экспрессии.info/lookaround.html
artemisian
2
Нет проблем. NumberFormatException это хорошо. Как узнать, какая запятая правильная? Неправильный формат, и все, что вы можете сделать, это показать пользователю более удобочитаемое сообщение, чем исключение.
Невероятный
2
@TheincredibleJan Нет, формат не неправильный. Некоторые локали используют запятую в качестве разделителя тысяч, так что вы можете иметь более одного из них в числе, и это технически все еще допустимый ввод.
Это работает только в том случае, если текущая локаль по умолчанию использует запятую в качестве десятичного разделителя.
Joonas Pulakka
6
Чтобы еще больше запутать ситуацию, некоторые локали используют запятую в качестве разделителя тысяч , и в этом случае «1234» будет анализировать 1234.0 вместо выдачи ошибки.
Joonas Pulakka
17
Проблема с NumberFormat заключается в том, что он будет игнорировать недопустимые символы. Поэтому, если вы попытаетесь проанализировать «1,23abc», он с радостью вернет 1.23, не указав вам, что переданная строка содержит непарсируемые символы. В некоторых ситуациях это может быть действительно желательно, но я не думаю, что это обычно желаемое поведение.
E-Riz
7
для ТУРЦИИ вы должны использовать NumberFormat.getInstance (новая локаль (tr_TR))
Да ... если мы не установим разделитель группировки тысяч и просто используем французский формат, число в испанском формате (1.222.222,33) будет преобразовано в «1 222 222,33», что не то, что я хочу , Так что спасибо!
WesternGun
1
Другое дело, что испанский языковой стандарт не указан как «по умолчанию», и я не могу создать Localeправильный формат с, new Locale("es", "ES")а затем автоматически проанализировать строку чисел с NumberFormat, ,в качестве десятичного разделителя и .как разделитель групп тысяч. DecimalFormatРаботает только .
WesternGun
Почему не все страны доступны там? Я чувствую себя странно об использовании французского языка для форматирования польских чисел ...
Строка
18
Как указывает E-Riz, NumberFormat.parse (String) анализирует "1,23abc" как 1,23. Чтобы взять весь ввод, мы можем использовать:
... очень быстро, так как он выполняет поиск в массиве символов на основе символьных символов. Строка замены версий компилирует RegEx для оценки.
Обычно замена (char, char) примерно в 10 раз быстрее, и, поскольку вы будете делать подобные вещи в низкоуровневом коде, имеет смысл подумать об этом. Оптимизатор Hot Spot не поймет этого ... Конечно, не в моей системе.
Это статический метод, который я использую в своем собственном коде:
publicstaticdouble sGetDecimalStringAnyLocaleAsDouble (String value){if(value ==null){Log.e("CORE","Null value!");return0.0;}Locale theLocale =Locale.getDefault();NumberFormat numberFormat =DecimalFormat.getInstance(theLocale);Number theNumber;try{
theNumber = numberFormat.parse(value);return theNumber.doubleValue();}catch(ParseException e){// The string value might be either 99.99 or 99,99, depending on Locale.// We can deal with this safely, by forcing to be a point for the decimal separator, and then using Double.valueOf ...//http://stackoverflow.com/questions/4323599/best-way-to-parsedouble-with-comma-as-decimal-separatorString valueWithDot = value.replaceAll(",",".");try{returnDouble.valueOf(valueWithDot);}catch(NumberFormatException e2){// This happens if we're trying (say) to parse a string that isn't a number, as though it were a number!// If this happens, it should only be due to application logic problems.// In this case, the safest thing to do is return 0, having first fired-off a log warning.Log.w("CORE","Warning: Value is not a number"+ value);return0.0;}}}
Что делать, если языковой стандарт по умолчанию похож на немецкий, где запятая обозначает десятичное место? Вы можете передать, например, «1 000 000», которые не будут разбираться в немецкой локали и затем будут заменены на «1 000 000», что не является действительным двойным числом.
Эдди Кертис
Привет @jimmycar, я только что обновил свой ответ, чтобы использовать текущую версию моего статического метода. Я надеюсь, что это решит вашу проблему! Пит
Пит
1
Вам, конечно, нужно использовать правильную локаль. Этот вопрос поможет.
В случае, если вы не знаете локаль полученного строкового значения, и она не обязательно совпадает с локалью текущей локали по умолчанию, вы можете использовать это:
Он вернет значение double независимо от того, какой будет строка в строке. И не важно, сколько там запятых или точек. Таким образом, передача 1,000,000.54будет работать, так 1.000.000,54что вам не придется больше полагаться на локаль по умолчанию для анализа строки. Код не так оптимизирован, как может быть, поэтому любые предложения приветствуются. Я пытался протестировать большинство случаев, чтобы убедиться, что это решает проблему, но я не уверен, что она охватывает все. Если вы найдете критическое значение, дайте мне знать.
В первом вопросе говорилось: «Есть ли лучший способ разобрать« 1,234 », чтобы получить 1,234, чем: p = p.replaceAll («, »,«. »); Если вы считаете, что replaceзначительно отличается от использования replaceAll, пожалуйста, объясните, почему.
replaceAll(",",".")
заменяет все запятые на точки. Если запятых нет, то ничего не происходит.Double.valueOf()
работает (только) со строками, которые используют точку в качестве десятичного разделителя. Ничто здесь не зависит от текущей локали по умолчанию. docs.oracle.com/javase/8/docs/api/java/lang/…replaceAll(",",".")
том, что он будет работать только при наличии единственной запятой: то есть: 1 234 567 выбрасываетjava.lang.NumberFormatException: multiple points
. Будет достаточно регулярного выражения с положительным взглядомp.replaceAll(",(?=[0-9]+,)", "").replaceAll(",", ".")
Подробнее на: регулярно-экспрессии.info/lookaround.htmlОтветы:
Используйте java.text.NumberFormat :
источник
Вы можете использовать это (французская локаль имеет
,
десятичный разделитель)Или вы можете использовать
java.text.DecimalFormat
и установить соответствующие символы:источник
Locale
правильный формат с,new Locale("es", "ES")
а затем автоматически проанализировать строку чисел сNumberFormat
,,
в качестве десятичного разделителя и.
как разделитель групп тысяч.DecimalFormat
Работает только .Как указывает E-Riz, NumberFormat.parse (String) анализирует "1,23abc" как 1,23. Чтобы взять весь ввод, мы можем использовать:
источник
... очень быстро, так как он выполняет поиск в массиве символов на основе символьных символов. Строка замены версий компилирует RegEx для оценки.
Обычно замена (char, char) примерно в 10 раз быстрее, и, поскольку вы будете делать подобные вещи в низкоуровневом коде, имеет смысл подумать об этом. Оптимизатор Hot Spot не поймет этого ... Конечно, не в моей системе.
источник
Если вы не знаете правильный Locale и строка может иметь разделитель тысяч, это может быть последним средством:
Имейте в виду: это с радостью проанализирует строки типа «R 1 52.43,2» до «15243.2».
источник
Это статический метод, который я использую в своем собственном коде:
источник
Вам, конечно, нужно использовать правильную локаль. Этот вопрос поможет.
источник
В случае, если вы не знаете локаль полученного строкового значения, и она не обязательно совпадает с локалью текущей локали по умолчанию, вы можете использовать это:
Он вернет значение double независимо от того, какой будет строка в строке. И не важно, сколько там запятых или точек. Таким образом, передача
1,000,000.54
будет работать, так1.000.000,54
что вам не придется больше полагаться на локаль по умолчанию для анализа строки. Код не так оптимизирован, как может быть, поэтому любые предложения приветствуются. Я пытался протестировать большинство случаев, чтобы убедиться, что это решает проблему, но я не уверен, что она охватывает все. Если вы найдете критическое значение, дайте мне знать.источник
Это сделало бы работу:
источник
replace
значительно отличается от использованияreplaceAll
, пожалуйста, объясните, почему.