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

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

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

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

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

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

Ответ 1

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

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

Откроется dexp: 12345678.000000. Если вы не хотите дробную часть, используйте

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

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

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

Ответ 2

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

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

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

Ответ 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
    

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

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

Две причины:

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

Ответ 4

Вы можете попробовать его с помощью DecimalFormat. С помощью этого класса вы очень гибко разбираете свои номера.
Вы можете точно установить шаблон, который хотите использовать.
Например, в вашем случае:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678

Ответ 5

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

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

Он выглядит так в кратчайшей форме:

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

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

if (myDouble.doubleValue() == 0)
    return "0";

NaN и бесконечные значения должны быть дополнительно проверены.

Конечный результат всех этих соображений:

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

    // Pre Java 8, a value of 0 would yield "0.0" below
    if (d.doubleValue() == 0)
        return "0";
    return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}

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

Ответ 6

Это будет работать до тех пор, пока ваш номер будет целым числом:

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

Если двойная переменная имеет точность после десятичной точки, она усекает ее.

Ответ 7

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

DecimalFormat был для меня способом, вот что я сделал:

   public String foo(double value) //Got here 6.743240136E7 or something..
    {
        DecimalFormat formatter;

        if(value - (int)value > 0.0)
            formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
        else
            formatter = new DecimalFormat("0");

        return formatter.format(value);
    }

Как вы можете видеть, если число естественное, я получаю - скажем - 20000000 вместо 2E7 (и т.д.) - без какой-либо десятичной точки.

И если он десятичный, я получаю только две десятичные цифры.

Ответ 8

Следующий код определяет, представлен ли предоставленный номер в научной нотации. Если это так, то оно представлено в нормальном представлении с максимальным числом "25".

 static String convertFromScientificNotation(double number) {
    // Check if in scientific notation
    if (String.valueOf(number).toLowerCase().contains("e")) {
        System.out.println("The scientific notation number'"
                + number
                + "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
        NumberFormat formatter = new DecimalFormat();
        formatter.setMaximumFractionDigits(25);
        return formatter.format(number);
    } else
        return String.valueOf(number);
}

Ответ 9

Компилятор Java/Kotlin преобразует любое значение больше 9999999 (больше или равно 10 миллионам) в научную нотацию, т.е. Epsilion обозначение.

Например: 12345678 преобразуется в 1.2345678E7

Используйте этот код, чтобы избежать автоматического преобразования в научную нотацию:

fun setTotalSalesValue(String total) {
        var valueWithoutEpsilon = total.toBigDecimal()
        /* Set the converted value to your android view using setText() function */
        totalSalesValue.setText() = valueWithoutEpsilon.toPlainString()
    }

Ответ 10

У меня была такая же проблема в моем производственном коде, когда я использовал его как строковый ввод в функцию math.Eval(), которая принимает строку типа "x + 20/50"

Я посмотрел на сотни статей... В конце концов я пошел с этим из-за скорости. И поскольку функция Eval собиралась преобразовать ее обратно в свой собственный формат номера в конечном итоге, а математика. Eval() не поддерживала конечный E-07, возвращаемый другими методами, и что-то более 5 dp было слишком большим для моего приложения в любом случае.

Это теперь используется в производственном коде для приложения с 1000+ пользователями...

double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp

s display as:  0.00021

Ответ 11

Я думаю, что у всех была правильная идея, но все ответы были непростыми. Я вижу, что это очень полезный фрагмент кода. Вот фрагмент того, что будет работать:

System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));

the ".8" - это то, где вы указываете количество десятичных знаков, которые вы хотели бы показать.

Я использую Eclipse, и это не сработало.

Надеюсь, это было полезно. Буду признателен за любую обратную связь!

Ответ 12

Для целочисленных значений, представленных double, вы можете использовать этот код, который намного быстрее, чем другие решения.

public static String doubleToString(final double d) {
    // check for integer, also see https://stackoverflow.com/a/9898613/868941 and
    // https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
    if (isMathematicalInteger(d)) {
        return Long.toString((long)d);
    } else {
        // or use any of the solutions provided by others
        return Double.toString(d);
    }
}

// Java 8+
public static boolean isMathematicalInteger(final double d) {
    return StrictMath.rint(d) == d && Double.isFinite(d);
}