Как вывести локализованные значения Java с плавающей запятой с полной точностью?
Если я отформатирую двойной, используя toString
метод, то я получаю полную точность двойной. Например (используя синтаксис Scala):
java.text.MessageFormat.format ("{0}", Math.PI.toString)
приведет к строке, содержащей:
3.141592653589793
Однако это значение не локализовано. Если я передам двойное значение в штучной упаковке Double
это как:
java.text.MessageFormat.format ("{0}", Math.PI.asInstanceOf[AnyRef])
(AnyRef
это тип Scala, который эквивалентен Object
в Java), то результатом будет локализованная строка с усеченной точностью:
3.142
Результат тот же, даже если я добавлю больше подсказки к строке формата:
java.text.MessageFormat.format ("{0,number}", Math.PI.asInstanceOf[AnyRef])
Я могу получить полную точность, указав пользовательский формат:
java.text.MessageFormat.format ("{0,number,#.###############}", Math.PI.asInstanceOf[AnyRef])
но это требует некоторых знаний о величине и точности двойника. Если я печатаю любое двойное значение (не только Pi) и хочу сохранить полную точность значения, то этот подход означает, что мне нужно динамически изменять строку формата - и это не совсем удобно, если (как в моем случае) строка формата фактически получена из пакета ресурсов.
Например, рассмотрим двойное значение 1.0e37
, Сначала преобразование в строку и использование "{0}" в качестве строки формата приводит к соответствующему, но не локализованному, строковому значению 1.0E37
, Если я передам это в штучной упаковке Double
со строкой формата "{0, число}", тогда я получаю смешное значение 10,000,000,000,000,000,000,000,000,000,000,000,000
,
Короче говоря, я не могу найти строку формата, которая сохраняет полную точность двойного без предварительного преобразования ее в строку - и это то, что я предпочел бы избежать, как чума. Есть ли строка числового формата, которая выводит полную точность двойного в качестве локализованного значения?
ОБНОВЛЕНИЕ:
Просто чтобы уточнить, почему я предпочел бы не преобразовывать двойные числа в строки:
toString
насколько я могу судить, возвращает действительное двойное литеральное значение Java. Как строка, результат не локализуется при передачеMessageFormat.format
, Например, я говорю, что я хочу вывести локализованную форму значения1234.567
,toString
вернется"1234.567"
, а такжеMessageFormat.format
оставил бы это в этом. Хорошо. У меня есть точный вывод. Однако в Германии это было бы более разумно, если бы"1.234,567"
, Даже в США / Великобритании это выглядело бы лучше, если бы"1,234.567"
,- Если я пройду в штучной упаковке
Integer
,Boolean
или любой другой не примитивный тип с плавающей точкойMessageFormat.format
(с простым форматом "{n}"), тогда я получаю хорошо локализованный вывод с полной точностью. Мне не нужно - и не следует, поскольку я потеряю локализованный вывод - сначала преобразовать эти значения в строки. Это означает, что я должен лечить двойников (и плавает иBigDecimal
s) по-разному и преобразовать их в строки перед передачей ихMessageFormat.format
, (Более того, я должен помнить, чтобы делать это каждый раз.)
2 ответа
MessageFormat использует локализованное представление с тысячами разделителей, возможно, десятичную запятую и так далее. В вашем использовании он использует язык по умолчанию вашей платформы.
Что-то, что следует хранить отдельно от записи универсального программиста, valueOf/toString.
С помощью double
а также precision
немного оксюморон, поскольку десятичное представление является приближением суммы степеней двойки, которой является дубль внутри.
Чтобы сохранить полную информацию, вы можете хранить необработанные биты в текстовой форме, используя Double.doubleToRawLongBits и обратно longBitsToDouble
,
double x = Math.PI;
String repr = String.format("%016x", Double.doubleToRawLongBits(x));
x = Double.longBitsToDouble(Long.valueOf(repr, 16));
Двойной формат в Java представлен 64 битами, для мантиссы используется 52 бита. log (252) = 15,65355977. Это означает, что точность Double составляет примерно 15-16 цифр.
Поэтому я думаю, что результат 3.141592653589793
это почти все, что вы можете получить от Double.