Double 64-bit dapat mewakili integer +/- 2 53 dengan tepat
Mengingat fakta ini saya memilih untuk menggunakan tipe ganda sebagai tipe tunggal untuk semua tipe saya, karena integer terbesar saya tidak bertanda 32-bit.
Tapi sekarang saya harus mencetak bilangan bulat semu ini, tetapi masalahnya adalah mereka juga bercampur dengan ganda yang sebenarnya.
Jadi bagaimana cara mencetak ganda ini dengan baik di Jawa?
Saya sudah mencoba String.format("%f", value)
, yang dekat, kecuali saya mendapatkan banyak angka nol untuk nilai kecil.
Berikut ini contoh keluaran dari %f
232.00000000 0,18000000000 1237875192.0 4.5800000000 0,00000000 1.23450000
Yang saya inginkan adalah:
232 0,18 1237875192 4.58 0 1.2345
Tentu saya bisa menulis fungsi untuk memangkas angka-angka itu, tapi itu banyak kehilangan kinerja karena manipulasi String. Bisakah saya melakukan yang lebih baik dengan kode format lain?
EDIT
Jawaban oleh Tom E. dan Jeremy S. tidak dapat diterima karena keduanya secara acak berputar ke 2 tempat desimal. Harap mengerti masalahnya sebelum menjawab.
EDIT 2
Harap perhatikan bahwa String.format(format, args...)
ini tergantung pada lokal (lihat jawaban di bawah).
System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
Jawaban:
Jika idenya adalah mencetak bilangan bulat yang disimpan sebagai ganda seolah-olah bilangan bulat, dan sebaliknya mencetak ganda dengan presisi minimum yang diperlukan:
Menghasilkan:
Dan tidak mengandalkan manipulasi string.
sumber
double
lebih besar dari nilai maksimumint
. Bahkan denganlong
itu masih akan gagal untuk jumlah besar. Selanjutnya ia akan mengembalikan sebuah String dalam bentuk eksponensial, misalnya "1.0E10", untuk nilai-nilai besar, yang mungkin bukan yang diinginkan penanya. Gunakan%f
alih-alih%s
di string format kedua untuk memperbaikinya.%f
. Jawabannya khusus untuk situasi yang dijelaskan, dan output yang diinginkan. OP menyarankan nilai maksimum mereka adalah 32-bit int unsigned, yang saya ambil untuk berarti bahwaint
dapat diterima (unsigned tidak benar-benar ada di Jawa, dan tidak ada contoh bermasalah), tetapi mengubahint
untuklong
adalah memperbaiki sepele jika situasinya berbeda.String.format("%s",d)
??? Bicara tentang overhead yang tidak perlu. GunakanDouble.toString(d)
. Sama untuk yang lain:Long.toString((long)d)
.%s
tidak berfungsi dengan Lokal. Dalam bahasa Jerman, kami menggunakan "," bukannya "." dalam angka desimal. SementaraString.format(Locale.GERMAN, "%f", 1.5)
mengembalikan "1.500000",String.format(Locale.GERMAN, "%s", 1.5)
mengembalikan "1,5" - dengan ".", Yang salah dalam bahasa Jerman. Apakah ada versi "% s" yang bergantung pada lokal juga?Seperti yang ditunjukkan dalam komentar, ini bukan jawaban yang tepat untuk pertanyaan awal.
Yang mengatakan, ini adalah cara yang sangat berguna untuk memformat angka tanpa membuntuti nol.
sumber
sumber
Pendeknya:
Jika Anda ingin menghilangkan angka nol dan masalah Lokal, maka Anda harus menggunakan:
Penjelasan:
Mengapa jawaban lain tidak cocok untuk saya:
Double.toString()
atauSystem.out.println
atauFloatingDecimal.toJavaFormatString
menggunakan notasi ilmiah jika dobel kurang dari 10 ^ -3 atau lebih besar dari atau sama dengan 10 ^ 7dengan 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:dengan menggunakan
setMaximumFractionDigits(0);
atau%.0f
Anda menghapus presisi desimal, yang baik untuk bilangan bulat / rindu tetapi tidak untuk gandadengan menggunakan DecimalFormat, Anda bergantung pada lokal. Di lokal Prancis, pemisah desimal adalah koma, bukan titik:
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:
setMaximumFractionDigits
menerima integer tetapi implementasinya memiliki angka maksimum yang diizinkanDecimalFormat.DOUBLE_FRACTION_DIGITS
yang sama dengan 340Double.MIN_VALUE = 4.9E-324
jadi dengan 340 digit Anda yakin untuk tidak membulatkan presisi ganda dan longgar Andasumber
0
alih-alih#.
DecimalFormat.DOUBLE_FRACTION_DIGITS
tetapi Anda menggunakan nilai 340, yang kemudian Anda berikan komentar untuk menunjukkan bahwa itu sama denganDecimalFormat.DOUBLE_FRACTION_DIGITS
. Mengapa tidak menggunakan konstanta saja ???Kenapa tidak:
Ini harus bekerja dengan nilai ekstrim yang didukung oleh Double. Hasil:
sumber
"%s"
pada dasarnya panggiland.toString()
tetapi tidak bekerja denganint
atau jikad==null
!Di komputer saya, fungsi berikut kira-kira 7 kali lebih cepat daripada fungsi yang disediakan oleh jawaban JasonD , karena itu menghindari
String.format
:sumber
2 sen saya:
sumber
return String.format(Locale.US, (n % 1 == 0 ? "%.0f" : "%.1f"), n);
.Tidak, sudahlah.
Kehilangan kinerja karena manipulasi String adalah nol.
Dan inilah kode untuk memotong akhir setelahnya
%f
sumber
Gunakan a
DecimalFormat
dansetMinimumFractionDigits(0)
sumber
setMaximumFractionDigits(2)
dansetGroupingUsed(false)
(OP tidak menyebutkannya tetapi dari contoh tampaknya diperlukan). Juga, test case kecil tidak sakit sejak sepele dalam kasus ini. Namun, karena saya pikir ini solusi paling sederhana, sebuah upvote adalah sebuah upvote :)sumber
Harap perhatikan bahwa
String.format(format, args...)
ini bergantung pada lokal karena memformat menggunakan lokal default pengguna, yaitu, mungkin dengan koma dan bahkan spasi di dalam seperti 123 456.789 atau 123.456.789 , yang mungkin tidak persis seperti yang Anda harapkan.Anda mungkin lebih suka menggunakan
String.format((Locale)null, format, args...)
.Sebagai contoh,
cetakan
dan inilah yang akan
String.format(format, args...)
dilakukan di berbagai negara.EDIT Ok, karena telah ada diskusi tentang formalitas:
sumber
Saya membuat
DoubleFormatter
untuk secara efisien mengkonversi sejumlah besar nilai ganda ke String yang bagus / rapi:Berikut kodenya:
Catatan: Saya menggunakan 2 fungsi dari pustaka GUAVA. Jika Anda tidak menggunakan GUAVA, kode sendiri:
sumber
Yang ini akan menyelesaikan pekerjaan dengan baik, saya tahu topiknya sudah tua, tetapi saya masih berjuang dengan masalah yang sama sampai saya tiba di sini. Saya harap seseorang menemukannya bermanfaat.
sumber
sumber
sumber
Jawaban terlambat tapi ...
Anda bilang Anda memilih untuk menyimpan nomor Anda dengan tipe ganda . Saya pikir ini bisa menjadi akar masalah karena memaksa Anda untuk menyimpan bilangan bulat menjadi ganda (dan karena itu kehilangan informasi awal tentang sifat nilai). Bagaimana dengan menyimpan nomor Anda dalam instance kelas Number (superclass dari Double dan Integer) dan mengandalkan polimorfisme untuk menentukan format yang benar dari setiap nomor?
Saya tahu itu mungkin tidak dapat diterima untuk refactor seluruh bagian dari kode Anda karena itu tetapi bisa menghasilkan output yang diinginkan tanpa kode tambahan / casting / parsing.
Contoh:
Akan menghasilkan output berikut:
sumber
Inilah yang saya pikirkan:
Sederhana satu liner, hanya dicetak ke int jika benar-benar perlu
sumber
Format harga dengan pengelompokan, pembulatan, tidak ada nol yang tidak perlu (ganda).
Aturan:
2.0000 = 2; 1.0100000 = 1.01
)2.010 = 2.01; 0.20 = 0.2
)1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0
)0
(null/-0 = 0
)$
(= $56/-$56
)101101.02 = $101,101.02
)Lebih banyak contoh:
Ditulis dalam Kotlin sebagai ekstensi menyenangkan Double (sebab digunakan di Android), tetapi dapat dikonversi ke Java dengan mudah, menyebabkan kelas java digunakan.
Cara Penggunaan:
Tentang DecimalFormat : https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
sumber
Saya harus menggunakan penyebab
d == (long)d
ini memberi saya pelanggaran dalam laporan sonarsumber
ini adalah hasil dari beberapa tes:
sumber
Berikut adalah dua cara untuk mencapainya. Pertama, cara yang lebih pendek (dan mungkin lebih baik):
Dan inilah cara yang lebih panjang dan mungkin lebih buruk:
sumber
Untuk Kotlin Anda dapat menggunakan ekstensi seperti:
sumber
Berikut jawaban lain yang memiliki opsi untuk menambahkan desimal SAJA JIKA desimal tidak nol.
sumber
Inilah jawaban yang benar-benar berfungsi (kombinasi jawaban berbeda di sini)
sumber
Saya tahu ini adalah utas yang sangat lama .. Tapi saya pikir cara terbaik untuk melakukan ini adalah sebagai berikut:
Keluaran:
Satu-satunya masalah adalah yang terakhir di mana .0 tidak dihapus. Tetapi jika Anda dapat hidup dengan itu maka ini bekerja paling baik. % .2f akan membulatkannya ke 2 angka desimal terakhir. Begitu juga DecimalFormat. Jika Anda membutuhkan semua tempat desimal tetapi bukan nol yang tertinggal maka ini bekerja paling baik.
sumber
System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));
akan dicetak1
Ini akan membuat string untuk menjatuhkan tailing 0-s.
sumber