Bagaimana cara mencetak nilai ganda tanpa notasi ilmiah menggunakan Java?

222

Saya ingin mencetak nilai ganda di Java tanpa bentuk eksponensial.

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

Ini menunjukkan notasi E ini: 1.2345678E7.

Saya ingin mencetaknya seperti ini: 12345678

Apa cara terbaik untuk mencegah hal ini?

Tercela
sumber

Jawaban:

116

Anda bisa menggunakan printf()dengan %f:

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

Ini akan dicetak dexp: 12345678.000000. Jika Anda tidak ingin bagian pecahan, gunakan

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

Ini menggunakan bahasa penentu format yang dijelaskan dalam dokumentasi .

toString()Format default yang digunakan dalam kode asli Anda dieja di sini .

NPE
sumber
1
tapi itu menunjukkan nilai dexp: 12345681.000000yang salah. Dan sebenarnya setelah itu saya ingin menampilkannya di halaman web saya di mana ia ditampilkan seperti ini. 1.2345678E7Apakah ada di mana saya dapat menyimpannya dalam bentuk double like 12345678dan cara lainnya?
Despicable
1
@despicable: Anda mungkin telah melihat versi jawaban yang lama dan tidak lengkap. Coba muat ulang halaman. Harus ada paragraf tentang %.0f.
NPE
@despicable Anda dapat menyimpan dexp sebagai int sehingga Anda dapat menggunakannya dengan mudah
Justin
10
IT ROUNDS OFF THE NOMOR
Bingung
6
%.0fmembulatkan angka. Apakah ada cara untuk hanya membuang nol yang tertinggal?
NurShomik
239

Java mencegah notasi E dalam dobel:

Lima cara berbeda untuk mengubah angka ganda menjadi angka normal:

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));
    }
}

Program ini mencetak:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Yang semuanya nilainya sama.

Protip: Jika Anda bingung mengapa angka-angka acak itu muncul di luar batas tertentu dalam nilai ganda, video ini menjelaskan: computerphile mengapa 0.1+ 0.2sama0.30000000000001 ?

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

Eric Leschinski
sumber
Terima kasih banyak atas jawabannya dan terutama tipnya .. Video itu memecahkan kebingungan saya.
AnujDeo
97

Pendeknya:

Jika Anda ingin menghilangkan angka nol dan masalah Lokal, maka Anda harus menggunakan:

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

Penjelasan:

Mengapa jawaban lain tidak cocok untuk saya:

  • Double.toString()atau System.out.printlnatauFloatingDecimal.toJavaFormatString menggunakan notasi ilmiah jika dobel kurang dari 10 ^ -3 atau lebih besar dari atau sama dengan 10 ^ 7
  • Dengan menggunakan %f, presisi desimal default adalah 6, jika tidak, Anda dapat meng-hardcode-nya, tetapi hasilnya nol tambahan yang ditambahkan jika Anda memiliki lebih sedikit desimal. Contoh:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
  • Dengan menggunakan setMaximumFractionDigits(0);atau %.0fAnda menghapus presisi desimal, yang baik untuk bilangan bulat / panjang, tetapi tidak untuk ganda:

    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
  • Dengan menggunakan DecimalFormat, Anda bergantung pada lokal. Di lokal Prancis, pemisah desimal adalah koma, bukan titik:

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

    Menggunakan lokal BAHASA INDONESIA memastikan Anda mendapatkan titik untuk pemisah desimal, di mana pun program Anda akan berjalan.

Mengapa menggunakan 340 lalu untuk setMaximumFractionDigits?

Dua alasan:

  • setMaximumFractionDigitsmenerima bilangan bulat, tetapi implementasinya memiliki angka maksimum yang diizinkan DecimalFormat.DOUBLE_FRACTION_DIGITSyang sama dengan 340
  • Double.MIN_VALUE = 4.9E-324 jadi dengan 340 digit Anda yakin untuk tidak membulatkan ganda dan kehilangan presisi.
JBE
sumber
Apa pendapat Anda tentang new BigDecimal(myvalue).toPlainString()Dari uraian di docs.oracle.com/javase/7/docs/api/java/math/… ), tidak segera jelas bagaimana perilakunya ketika diberikan berbagai jenis angka, tetapi tidak menghilangkan notasi ilmiah .
Derek Mahar
4
new BigDecimal(0.00000021d).toPlainString()output 0.0000002100000000000000010850153241148685623329583904705941677093505859375yang tidak seperti yang Anda harapkan ...
JBE
tahu bagaimana cara menggunakan jawaban Anda di scala? mungkin masalah impor yang sesuai tapi saya baru di sini.
jangorecki
BigDecimal.valueOf(0.00000021d).toPlainString()berfungsi juga (menggunakan konstruktor String BigDecimal itu sebabnya)
marco
27

Anda bisa mencobanya dengan DecimalFormat. Dengan kelas ini Anda sangat fleksibel dalam mem-parsing nomor Anda.
Anda dapat dengan tepat mengatur pola yang ingin Anda gunakan.
Dalam kasus Anda misalnya:

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

Saya punya solusi lain yang melibatkan BigDecimal toPlainString (), tetapi kali ini menggunakan String-constructor, yang direkomendasikan di javadoc:

konstruktor ini kompatibel dengan nilai yang dikembalikan oleh Float.toString dan Double.toString. Ini umumnya merupakan cara yang disukai untuk mengubah float atau dobel menjadi BigDecimal, karena tidak mengalami ketidakpastian dari konstruktor BigDecimal (dobel).

Sepertinya ini dalam bentuk terpendek:

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

Sebelum Java 8, ini menghasilkan "0,0" untuk Doubles bernilai nol, jadi Anda perlu menambahkan:

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

Nilai NaN dan tak terbatas harus diperiksa ekstra.

Hasil akhir dari semua pertimbangan ini:

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();
}

Ini juga dapat disalin / ditempelkan agar berfungsi dengan baik dengan Float.

Manuel
sumber
2
Saya telah membaca skema yang tak terhitung jumlahnya untuk mengonversi nilai ganda menjadi String dan ini adalah yang terbaik: pendek, mudah, dapat dikonfigurasi.
Paul
Solusi hebat, benar-benar membantu saya mengubah nilai ganda menjadi String dan menghindari notasi ilmiah. Terima kasih!
Minggir
Kenapa d.doubleValue() == 0bukannya d == 0?
Alexei Fando
Karena itu menghindari auto-unboxing, yang saya sukai lebih baik dalam situasi itu, tetapi pandangan tentu saja berbeda dalam hal ini. Jika Anda menggunakan java 8 (9 mungkin akan sama), Anda dapat mengabaikan 2 baris itu sekaligus.
Manuel
Baru saja mencoba dengan java 9, 2 baris tersebut dapat ditinggalkan pada 9 juga.
Manuel
8

Ini akan berfungsi selama nomor Anda adalah angka utuh:

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

Jika variabel ganda memiliki presisi setelah titik desimal, ia akan memotongnya.

NateS
sumber
4

Saya perlu mengonversi beberapa nilai ganda menjadi mata uang dan menemukan bahwa sebagian besar solusi tidak masalah, tetapi tidak untuk saya.

Ini DecimalFormatakhirnya menjadi jalan saya, jadi inilah yang telah saya lakukan:

   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);
    }

Seperti yang Anda lihat, jika angka itu alami saya dapatkan - katakan - 20000000 bukannya 2E7 (dll.) - tanpa titik desimal.

Dan jika itu desimal, saya hanya mendapatkan dua digit desimal.

JamesC
sumber
4

Kompiler Java / Kotlin mengkonversi nilai apa pun yang lebih besar dari 9999999 (lebih besar dari atau sama dengan 10 juta) menjadi notasi ilmiah yaitu. Notasi Epsilion .

Mis: 12345678 dikonversi menjadi 1.2345678E7

Gunakan kode ini untuk menghindari konversi otomatis ke notasi ilmiah:

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

Kode berikut mendeteksi jika nomor yang disediakan disajikan dalam notasi ilmiah. Jika demikian, itu direpresentasikan dalam presentasi normal dengan maksimum '25' digit.

 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);
}
Memin
sumber
1

Saya pikir semua orang punya ide yang tepat, tetapi semua jawaban tidak langsung. Saya bisa melihat ini menjadi bagian kode yang sangat berguna. Berikut ini cuplikan dari apa yang akan berfungsi:

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

yang ".8"adalah tempat Anda mengatur jumlah tempat desimal Anda ingin menunjukkan.

Saya menggunakan Eclipse dan tidak ada masalah.

Semoga ini bermanfaat. Saya sangat menghargai umpan balik!

Brian Castro
sumber
1

Saya memiliki masalah yang sama dalam kode produksi saya ketika saya menggunakannya sebagai input string ke fungsi math.Eval () yang mengambil string seperti "x + 20/50"

Saya melihat ratusan artikel ... Pada akhirnya saya pergi dengan ini karena kecepatan. Dan karena fungsi Eval akan mengubahnya kembali ke dalam format angka sendiri dan akhirnya matematika. .

Ini sekarang digunakan dalam kode produksi untuk aplikasi yang memiliki 1.000 pengguna ...

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

s display as:  0.00021
hamish
sumber
1

Ini mungkin tangen .... tetapi jika Anda harus meletakkan nilai numerik sebagai integer (yang terlalu besar untuk menjadi integer) ke dalam serializer (JSON, dll.) Maka Anda mungkin ingin "BigInterger"

Contoh: nilai adalah string - 7515904334

Kita perlu menggambarkannya sebagai angka dalam pesan Json: {"contact_phone": "800220-3333", "servicer_id": 7515904334, "servicer_name": "SOME CORPORATION"}

Kami tidak dapat mencetaknya atau kami akan mendapatkan ini: {"contact_phone": "800220-3333", "servicer_id": "7515904334", "servicer_name": "SOME CORPORATION"}

Menambahkan nilai ke simpul seperti ini menghasilkan hasil yang diinginkan: BigInteger.valueOf (Long.parseLong (value, 10))

Saya tidak yakin ini benar-benar sesuai topik, tetapi karena pertanyaan ini adalah hit teratas saya ketika saya mencari solusi, saya pikir saya akan berbagi di sini untuk kepentingan orang lain, bohong, yang pencariannya buruk. : D

Keith Fosberg
sumber
-1

Untuk nilai integer yang diwakili oleh a double, Anda dapat menggunakan kode ini, yang jauh lebih cepat daripada solusi lain.

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);
}
ruller
sumber
-1

Solusi saya: String str = String.format ("% .0f", yourDouble);

Nguyễn Thắng
sumber