Як надрукувати подвійне значення без наукових позначень за допомогою Java?


223

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

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

Це показує , що це E позначення: 1.2345678E7.

Я хочу, щоб він надрукував це так: 12345678

Який найкращий спосіб запобігти цьому?

Відповіді:


116

Ви можете використовувати printf()з %f:

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

Це надрукується dexp: 12345678.000000. Якщо ви не хочете дробової частини, використовуйте

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

Для цього використовується мова специфікатора формату, пояснена в документації .

За замовчуванням toString()формат , який використовується в вихідному коді прописано тут .


1
але я показав, dexp: 12345681.000000що це неправильне значення. Насправді після цього я хочу відобразити його на своїй веб-сторінці, де вона відображається так. 1.2345678E7Чи є в будь-якому випадку, через яку я можу зберігати його в будь-якому подвійному вигляді 12345678і будь-яким іншим способом?
зневірене

1
@despicable: Можливо, ви шукали стару, неповну версію відповіді. Спробуйте перезавантажити сторінку. Тут має бути абзац про %.0f.
NPE

@despicable ви можете зберігати dexp як int, щоб ви могли легко використовувати його обома способами
Джастін,

10
ЇЇ КРУГЛИ З НОМЕРА
Плутати

6
%.0fокругляє число. Чи є спосіб просто відкинути останні нулі?
NurShomik

239

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

Які мають однакове значення.

Підказка: Якщо вас плутають, чому ці випадкові цифри з’являються за певним порогом у подвійному значенні, це відео пояснює: комп'ютерний, чому 0.1+ 0.2дорівнює 0.30000000000001?

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


Дуже дякую за відповідь і особливо підказку .. Це відео вирішило мою плутанину.
AnujDeo

98

Коротко:

Якщо ви хочете позбутися від нульових нулів та проблем з локальним розташуванням, тоді слід скористатися:

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використовує наукові позначення, якщо подвійне менше 10 ^ -3 або більше або дорівнює 10 ^ 7
  • За допомогою %fдесяткової точності за замовчуванням дорівнює 6, інакше ви можете жорстко кодувати її, але це призводить до додаткових нулів, якщо у вас менше десяткових знаків. Приклад:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
  • Використовуючи setMaximumFractionDigits(0);або %.0fвидаляючи будь-яку десяткову точність, що добре для цілих чисел / довгих, але не для подвійної:

    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 цифр, ви впевнені, що не округлите свій подвійний і не втратите точність.

Як ви думаєте з new BigDecimal(myvalue).toPlainString()опису на docs.oracle.com/javase/7/docs/api/java/math/… ), не відразу зрозуміло, як він поводиться, коли даються різні типи чисел, але це усуває наукові позначення .
Дерек Махар

4
new BigDecimal(0.00000021d).toPlainString()вихід, 0.0000002100000000000000010850153241148685623329583904705941677093505859375який не є таким, якого б ви очікували ...
JBE

будь-яка ідея, як використовувати свою відповідь у масштабі? певно, це питання відповідного імпорту, але я тут новий.
jangorecki

BigDecimal.valueOf(0.00000021d).toPlainString()працює також (для цього використовується конструктор String BigDecimal)
marco

27

Ви можете спробувати DecimalFormat. З цим класом ви дуже гнучкі в розборі своїх цифр.
Ви можете точно встановити шаблон, який ви хочете використовувати.
Наприклад, у вашому випадку:

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

16

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

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

Це виглядає так у найкоротшому вигляді:

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

Перед 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.


2
Я прочитав незліченну кількість схем для перетворення подвійного значення в String, і це найкраще: коротка, проста, налаштована.
Павло

Чудове рішення, дійсно допомогло мені перетворити подвійні значення на String і уникати наукових позначень. Дякую!
pleft

Чому d.doubleValue() == 0замість d == 0?
Олексій Фандо

Тому що це дозволяє уникнути автоматичного розпакування, що мені подобається в цій ситуації, але погляди на це, звичайно, можуть відрізнятися. Якщо ви на Java 8 (9, мабуть, буде те саме), ви можете взагалі залишити ці 2 рядки.
Мануель

Щойно спробувавши з java 9, ці 2 рядки також можуть залишитися на 9.
Мануель

8

Це працюватиме до тих пір, поки ваш номер буде цілим числом:

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

Якщо подвійна змінна має точність після десяткової крапки, вона вріже її.


4

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

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 (тощо) - без десяткової крапки.

І якщо це десятковий, я отримую лише дві десяткові цифри.


4

Компілятор Java / Kotlin перетворює будь-яке значення, що перевищує 9999999 (більше або дорівнює 10 мільйонам) у наукові позначення, тобто. Позначення епсіліона .

Наприклад: 12345678 перетворено на 1.2345678E7

Використовуйте цей код, щоб уникнути автоматичного переходу на наукові позначення:

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

3

Наступний код визначає, чи вказане число представлено в науковій нотації. Якщо так, то він представлений у звичайній подачі максимум "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);
}

2

Я думаю, що кожен мав правильну ідею, але всі відповіді не були однозначними. Я бачу, що це дуже корисний фрагмент коду. Ось фрагмент того, що буде працювати:

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

".8"де ви встановите кількість знаків після коми ви хотіли б показати.

Я використовую Eclipse, і це спрацювало без проблем.

Сподіваюся, що це було корисно. Буду вдячний за будь-які відгуки!


1

Цю проблему я мав у своєму виробничому коді, коли я використовував її як введення рядка до функції math.Eval (), яка приймає рядок типу "x + 20/50"

Я переглянув сотні статей ... Зрештою, я пішов з цим через швидкість. А тому що функція Eval збиралася перетворити його назад у свій власний формат чисел, і math.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

1

Це може бути дотичною .... але якщо вам потрібно ввести серіалізатор (JSON та ін.) Числове значення як ціле число (яке занадто велике, щоб бути цілим числом), ви, ймовірно, хочете "BigInterger"

Приклад: значення - рядок - 7515904334

Нам потрібно представити це як числове повідомлення у повідомленні Json: {"contact_phone": "800220-3333", "servicer_id": 7515904334, "servicer_name": "ДЕЯКА КОРПОРАЦІЯ"}

Ми не можемо роздрукувати його або отримаємо це: {"contact_phone": "800220-3333", "servicer_id": "7515904334", "servicer_name": "ДЕЯКА КОРПОРАЦІЯ"}

Додавання значення до такого вузла дає бажаний результат: BigInteger.valueOf (Long.parseLong (значення, 10))

Я не впевнений, що це насправді на тему, але оскільки це питання було моїм найкращим хітом, коли я шукав своє рішення, я думав, що поділюсь тут на благо інших, брешу мені, хто погано шукає. : D


-1

Для цілих значень, представлених символом a 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);
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.