Вопрос-ответ

How do I print a double value without scientific notation using Java?

Как мне напечатать двойное значение без научной нотации с помощью Java?

Я хочу напечатать двойное значение в Java без экспоненциальной формы.

double dexp = 12345678;
System.out.println("dexp: "+dexp);

Он показывает это обозначение E: 1.2345678E7.

Я хочу, чтобы это было напечатано следующим образом: 12345678

Каков наилучший способ предотвратить это?

Переведено автоматически
Ответ 1

Java предотвращает запись E в double:

Пять различных способов преобразовать значение double в обычное число:

import java.math.BigDecimal;
import java.text.DecimalFormat;

public class Runner {
public static void main(String[] args) {
double myvalue = 0.00000021d;

//Option 1 Print bare double.
System.out.println(myvalue);

//Option2, use decimalFormat.
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(8);
System.out.println(df.format(myvalue));

//Option 3, use printf.
System.out.printf("%.9f", myvalue);
System.out.println();

//Option 4, convert toBigDecimal and ask for toPlainString().
System.out.print(new BigDecimal(myvalue).toPlainString());
System.out.println();

//Option 5, String.format
System.out.println(String.format("%.12f", myvalue));
}
}

Эта программа печатает:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Все это одно и то же значение.

Подсказка: Если вы не понимаете, почему эти случайные цифры появляются за определенным порогом в двойном значении, в этом видео объясняется: computerphile почему 0.1+0.2 равно 0.30000000000001?

http://youtube.com/watch?v=PZRI1IfStY0

Ответ 2

Вы могли бы использовать printf() с %f:

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);

Это выведетdexp: 12345678.000000. Если вам не нужна дробная часть, используйте

System.out.printf("dexp: %.0f\n", dexp);

0 в %.0f означает 0 мест в дробной части, т. е. без дробной части. Если вы хотите напечатать дробную часть с желаемым количеством знаков после запятой, то вместо 0 просто укажите число, подобное этому %.8f. По умолчанию дробная часть печатается с точностью до 6 знаков после запятой.

При этом используется язык спецификатора формата, описанный в документации.

По умолчанию toString() формат, используемый в вашем исходном коде, указан здесь.

Ответ 3

Вкратце:

Если вы хотите избавиться от завершающих нулей и проблем с локализацией, то вам следует использовать:

double myValue = 0.00000021d;

DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS

System.out.println(df.format(myValue)); // Output: 0.00000021

Объяснение:

Почему другие ответы меня не устроили:


  • Double.toString() или System.out.println или FloatingDecimal.toJavaFormatString использует научные обозначения, если значение double меньше 10 ^ -3 или больше или равно 10 ^ 7

  • При использовании %f десятичная точность по умолчанию равна 6, в противном случае вы можете закодировать ее жестко, но это приведет к добавлению дополнительных нулей, если у вас меньше десятичных знаков. Пример:


    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000

  • Используя setMaximumFractionDigits(0); или %.0f, вы удаляете любую десятичную точность, что подходит для целых чисел / длин, но не для double:


    double myValue = 0.00000021d;
    System.out.println(String.format("%.0f", myvalue)); // Output: 0
    DecimalFormat df = new DecimalFormat("0");
    System.out.println(df.format(myValue)); // Output: 0

  • Используя DecimalFormat, вы зависите от локального. Во французском языке десятичным разделителем является запятая, а не точка:


    double myValue = 0.00000021d;
    DecimalFormat df = new DecimalFormat("0");
    df.setMaximumFractionDigits(340);
    System.out.println(df.format(myvalue)); // Output: 0,00000021

    Использование английской локали гарантирует, что вы получите точку вместо десятичного разделителя, где бы ни запускалась ваша программа.


Зачем тогда использовать 340 для setMaximumFractionDigits?

Две причины:


  • setMaximumFractionDigits принимает целое число, но его реализация имеет максимально допустимые цифры из DecimalFormat.DOUBLE_FRACTION_DIGITS, которые равны 340

  • Double.MIN_VALUE = 4.9E-324 таким образом, при 340 цифрах вы точно не будете округлять значение double и терять точность.

Ответ 4

У меня есть другое решение, включающее функцию BigDecimal toPlainString(), но на этот раз с использованием String-конструктора, который рекомендуется в javadoc:


этот конструктор совместим со значениями, возвращаемыми Float.toString и Double.toString . Обычно это предпочтительный способ преобразования float или double в BigDecimal , поскольку он не страдает от непредсказуемости конструктора BigDecimal (double).


В самом коротком виде это выглядит так:

return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();

Значения NaN и infinite должны быть дополнительно проверены, поэтому в полном виде выглядит так:

public static String doubleToString(Double d) {
if (d == null)
return null;
if (d.isNaN() || d.isInfinite())
return d.toString();

return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}

Это также можно скопировать / вставить, чтобы хорошо работать с Float.

Для Java 7 и ниже это приводит к "0.0" для любых двойных значений с нулевым значением, поэтому вам нужно будет добавить:

if (d.doubleValue() == 0)
return "0";
java