Количество значащих цифр в научной записи с помощью DecimalFormat
Я пытаюсь полностью понять точное поведение DecimalFormat. В настоящее время я делаю некоторые тесты с возможностями научного обозначения этого класса. И я сталкиваюсь с проблемой с настройкой точного числа значащих цифр в научной нотации. Согласно Javadoc Java 7:
Количество значащих цифр в мантиссе является суммой минимальных целых и максимальных дробных цифр и не зависит от максимальных целых цифр. Например, 12345, отформатированный с "##0.##E0", равен "12.3E3". Чтобы показать все цифры, установите количество значащих цифр в ноль. Количество значащих цифр не влияет на разбор.
Следовательно, я проверяю это:
DecimalFormat formatone = new DecimalFormat("##0.##E0");
System.out.println(formatone.format(toF));
И я получаю следующий вывод:
12,345E3
Согласно отрывку из Javadoc, который я только что показал, я думал, что должен получить
12.3E3
Я делаю что-то неправильно? Я понял что-то не так?
Заранее спасибо за все ваши разъяснения:-)
1 ответ
Я напечатал значения для минимальных / максимальных целых / дробных цифр в случае "##0.##E0" и проверил результаты, полученные @Agemen:
DecimalFormat df = new DecimalFormat( "##0.##E0" );
System.out.printf("getMinimumIntegerDigits=%d\n", df.getMinimumIntegerDigits() );
System.out.printf("getMaximumIntegerDigits=%d\n", df.getMaximumIntegerDigits() );
System.out.printf("getMinimumFractionDigits=%d\n", df.getMinimumFractionDigits() );
System.out.printf("getMaximumFractionDigits=%d\n", df.getMaximumFractionDigits() );
double v = 12345;
System.out.printf("s=%f\n", v );
System.out.printf("r=%s\n", df.format(v) );
с результатом:
getMinimumIntegerDigits=1
getMaximumIntegerDigits=3
getMinimumFractionDigits=0
getMaximumFractionDigits=2
s=12345.000000
r=12.345E3
На мой взгляд, это ошибка в реализации Java или в документации, ожидаемый результат не получен.
О примере, приведенном в ответе @JoopEggen, он не применим, потому что шаблон "##0.#####E0"
имеет максимальное количество цифр дроби, равное 5.
На самом деле, ожидаемая строка получается с использованием шаблона "##0.E0"
,
Ошибка, вероятно, в файле DecimalFormat.java, в заявлении:
digitList.set(isNegative, number,
useExponentialNotation ?
maxIntDigits + maxFraDigits : maxFraDigits,
!useExponentialNotation);
Где дополнение "maxIntDigits + maxFraDigits" должно быть "minIntDigits + maxFraDigits", чтобы согласиться с документацией Java.
Вы игнорируете ту часть, которая говорит the mantissa is the sum of the minimum integer and maximum fraction digits
Чтобы получить желаемый результат, вам нужно установить эти значения:
DecimalFormat formatone = new DecimalFormat("##0.##E0");
formatone.setMinimumIntegerDigits(2);
formatone.setMaximumFractionDigits(0);
System.out.println(formatone.format(12345));
Из http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html вытекает следующее "объяснение". Чудеса
Минимальное и максимальное количество целых цифр интерпретируются вместе:
Если максимальное количество целочисленных цифр больше, чем их минимальное число и больше 1, это означает, что показатель степени кратен максимальному количеству целых цифр, а минимальное число целых цифр должно интерпретироваться как 1. Наиболее распространенная использование этого должно генерировать инженерную нотацию, в которой показатель степени кратен трем, например, "##0.#####E0". Используя этот шаблон, число 12345 форматируется до "12.345E3", а 123456 форматируется до "123.456E3".
Обязательно управляйте десятичными и групповыми разделителями при форматировании десятичных дробей.
Это способ сделать это (обратите внимание на все варианты шаблона формата):
@Test
public void test() {
double toF = 12345;
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
decimalFormatSymbols.setDecimalSeparator('.');
decimalFormatSymbols.setGroupingSeparator(',');
System.out.println((new DecimalFormat("#.#E0", decimalFormatSymbols)).format(toF));
System.out.println((new DecimalFormat("#0.#E0", decimalFormatSymbols)).format(toF));
System.out.println((new DecimalFormat("##0.#E0", decimalFormatSymbols)).format(toF));
System.out.println((new DecimalFormat("##0.##E0", decimalFormatSymbols)).format(toF));
System.out.println((new DecimalFormat("##0.###E0", decimalFormatSymbols)).format(toF));
}
Это выводит:
1.2E4
1.23E4
12.34E3
12.345E3
12.345E3
Вы можете получить дополнительную информацию в Документации API Java 8, которая может быть более новой, чем та, которую вы рассматривали до сих пор.