Число значащих цифр в научной нотации с DecimalFormat

Я пытаюсь полностью понять точное поведение DecimalFormat. В настоящее время я делаю некоторые тесты с возможностями научной нотации этого класса. И у меня возникла проблема с настройкой точного количества значимых цифр в научной нотации. Согласно Javadoc Java 7:

Число значащих цифр в мантиссе - это сумма минимальные значения целых и максимальных цифр, и на них не влияет максимальные целые цифры. Например, 12345, отформатированный с помощью "## 0. ## E0", "12.3E3". Чтобы показать все цифры, установите значащие цифры в нуль. Число значимых цифр не влияет на разбор.

Следовательно, я тестирую его:

DecimalFormat formatone = new DecimalFormat("##0.##E0");
System.out.println(formatone.format(toF));

И я получаю следующий вывод:

12,345E3

Согласно отрывке Джавадока, который я только что показал, я думал, что должен получить

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.

Ответ 2

Вы игнорируете часть, которая говорит, 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));

Ответ 3

Из http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html вытекает следующее "объяснение". Интересно.

Минимальное и максимальное число целых цифр интерпретируются вместе:

Если максимальное число целых цифр больше их минимального числа и больше 1, оно заставляет экспонента быть кратным максимальному числу целых цифр, а минимальное число целых цифр - 1. Наиболее частое использование этого метода заключается в создании машинописных обозначений, в которых показатель экспоненты кратен трем, например, "## 0. ##### E0". Используя этот шаблон, число 12345 форматов составляет "12.345E3" и 123456 форматов до "123.456E3".

Ответ 4

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

Это способ сделать это (обратите внимание на все варианты шаблона формата):

@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, которая может быть новее той, которую вы рассматривали до сих пор.