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

Другие вопросы по тегам