DecimalFormat и Double.valueOf ()

Я пытаюсь избавиться от ненужных символов после десятичного разделителя моего двойного значения. Я делаю его этот путь:

DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));

Но когда я выполняю этот код, он бросает:

java.lang.NumberFormatException: For input string: "41251,5"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
    at java.lang.Double.valueOf(Double.java:447)
    at ...

Поскольку я вижу, Double.valueOf() работает отлично со строками как "11.1", но это дросселирует на строках как "11,1". Как я работаю вокруг этого? Есть ли более изящный путь затем что-то как

Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));

Есть ли способ переопределить десятичное значение разделителя по умолчанию DecimalFormat класс? Какие-либо другие мысли?

12
задан folone 22 April 2010 в 13:09
поделиться

7 ответов

В

избавьтесь от ненужных символов после десятичного разделителя моего двойного значения

, вы действительно имеете в виду, что хотите округлить, например, пятый десятичный знак? Затем просто используйте

value = Math.round(value*1e5)/1e5;

(конечно, вы также можете Math.floor (value * 1e5) / 1e5 , если вы действительно хотите обрезать другие цифры)

78
ответ дан 2 December 2019 в 02:49
поделиться

Тот факт, что ваша строка форматирования использует . в качестве десятичного разделителя, в то время как исключение жалуется на , указывает на проблему с языковым стандартом; то есть DecimalFormat использует другой языковой стандарт для форматирования числа, чем ожидает Double.valueOf.

В общем, вы должны создать NumberFormat на основе определенного языкового стандарта.

Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);

Из JavaDocs DecimalFormat :

Чтобы получить NumberFormat для определенного языкового стандарта, включая языковой стандарт по умолчанию, вызовите один из заводских методов NumberFormat, например getInstance (). В общем, не вызывайте конструкторы DecimalFormat напрямую, поскольку методы фабрики NumberFormat могут возвращать подклассы, отличные от DecimalFormat.

Однако , как указывает BalusC , попытка отформатировать double как String, а затем разобрать String обратно на double - довольно неприятный запах кода. Я подозреваю, что вы имеете дело с проблемами, при которых вы ожидаете десятичное число с фиксированной точностью (например, денежная сумма), но сталкиваетесь с проблемами, потому что double - это число с плавающей запятой, что означает, что многие значения (например, 0.1 ) не может быть точно выражен как double / float. В этом случае правильным способом обработки десятичных чисел с фиксированной точностью является использование BigDecimal .

6
ответ дан 2 December 2019 в 02:49
поделиться

Проблема в том, что ваш десятичный формат преобразует ваше значение в локализованную строку. Я предполагаю, что ваш десятичный разделитель по умолчанию для вашей локали - «, ». Это часто случается с французскими регионами или другими частями мира.

По сути, вам нужно создать форматированную дату с помощью символа '.' разделитель, чтобы Double.valueOf мог его прочитать. Как указано в комментариях, вы можете использовать тот же формат для анализа значения вместо использования Double.valueOf .

DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
24
ответ дан 2 December 2019 в 02:49
поделиться

Вы не можете изменить внутреннее представление double / Double таким образом.

Если вы хотите изменить (человеческое) представление, просто оставьте его String . Таким образом, оставьте этот Double # valueOf () подальше и используйте результат String результата DecimalFormat # format () в своей презентации. Если вы когда-нибудь захотите провести с ним вычисления, вы всегда можете преобразовать обратно в реальный Double , используя DecimalFormat и Double # valueOf () .

Кстати, согласно вашей жалобе я пытаюсь избавиться от ненужных символов после десятичного разделителя моего двойного значения , знаете ли вы о внутреннем устройстве чисел с плавающей запятой ? Это немного пахнет тем, что вы используете неформатированные двойники на уровне представления и что вы не понимали, что со средним пользовательским интерфейсом вы можете просто представить их, используя DecimalFormat , без необходимости конвертировать обратно в ] Двойной .

2
ответ дан 2 December 2019 в 02:49
поделиться

Используйте Locale.getDefault () , чтобы получить десятичный разделитель вашей системы, который вы также можете установить. Вы не можете использовать разные разделители одновременно, поскольку другой обычно используется как разделитель для тысяч: 2,001,000,23 <=> 2,001,000,23

5
ответ дан 2 December 2019 в 02:49
поделиться

Для «, » вместо «. ', вам придется изменить языковой стандарт.

Для количества десятичных знаков используйте setMaximumFractionDigits (int newValue) .

Остальное см. В javadoc .

3
ответ дан 2 December 2019 в 02:49
поделиться

В некоторой степени связано с этим, но не является ответом на вопрос: попробуйте переключиться на BigDecimal вместо удвоений и чисел с плавающей запятой. У меня было много проблем со сравнением этих типов, и теперь я могу использовать BigDecimal.

2
ответ дан 2 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: