Apa yang saya inginkan adalah metode untuk mengkonversi ganda menjadi string yang dibulatkan menggunakan metode setengah naik - yaitu jika desimal yang dibulatkan adalah 5, selalu dibulatkan ke angka berikutnya. Ini adalah metode standar pembulatan yang kebanyakan orang harapkan dalam kebanyakan situasi.
Saya juga ingin hanya digit signifikan yang ditampilkan - yaitu tidak boleh ada nol tambahan.
Saya tahu salah satu metode melakukan ini adalah dengan menggunakan String.format
metode ini:
String.format("%.5g%n", 0.912385);
pengembalian:
0.91239
yang hebat, namun selalu menampilkan angka dengan 5 tempat desimal meskipun tidak signifikan:
String.format("%.5g%n", 0.912300);
pengembalian:
0.91230
Metode lain adalah dengan menggunakan DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
pengembalian:
0.91238
Namun seperti yang Anda lihat ini menggunakan pembulatan setengah-setengah. Itu akan dibulatkan ke bawah jika angka sebelumnya genap. Yang saya suka adalah ini:
0.912385 -> 0.91239
0.912300 -> 0.9123
Apa cara terbaik untuk mencapai ini di Jawa?
"#.##"
:, pembulatanHALF_UP
.256.335f
->"256.33"
... (contoh berasal dari komentar hingga jawaban @ asterite).Dengan asumsi
value
adalahdouble
, Anda dapat melakukan:Itu untuk presisi 5 digit. Jumlah nol menunjukkan jumlah desimal.
sumber
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.265.335
sangat berarti265.335 += tolerance
, di mana toleransi bergantung pada operasi sebelumnya dan kisaran nilai input. Kami tidak tahu nilai sebenarnya dan tepat. Pada nilai-nilai tepi, baik jawaban ini bisa dibilang benar. Jika kita harus tepat, kita seharusnya tidak bekerja ganda. Difail
sini bukan dalam mengkonversi kembali menjadi dua kali lipat. Itu dalam pemikiran OP dia bisa mengandalkan masuk265.335
sebagai persis seperti itu.akan membuat Anda
BigDecimal
. Untuk mendapatkan string dari itu, hanya menyebut bahwaBigDecimal
'stoString
metode, atautoPlainString
metode untuk Java 5 + untuk format string polos.Program sampel:
sumber
new BigDecimal(doubleVar)
karena Anda dapat mengalami masalah dengan pembulatan poin mengambangdouble val = 265.335;
,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.34
, tetapi(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.33
.Anda juga dapat menggunakan
untuk memastikan Anda memiliki 0 yang tertinggal.
sumber
RoundingMode.
Decimal mode
menggunakanRoundingMode.HALF_EVEN.
Seperti beberapa orang lain catat, jawaban yang benar adalah menggunakan salah satu
DecimalFormat
atauBigDecimal
. Floating-point tidak memiliki tempat desimal sehingga Anda tidak dapat membulatkan / memotong ke jumlah tertentu di tempat pertama. Anda harus bekerja dalam radix desimal, dan itulah yang dilakukan kedua kelas itu.Saya memposting kode berikut sebagai contoh balasan untuk semua jawaban di utas ini dan memang di seluruh StackOverflow (dan di tempat lain) yang merekomendasikan perkalian diikuti oleh pemotongan diikuti oleh pembagian. Merupakan kewajiban para pendukung teknik ini untuk menjelaskan mengapa kode berikut menghasilkan output yang salah di lebih dari 92% kasus.
Output dari program ini:
EDIT: Untuk membahas beberapa komentar di bawah ini saya redid bagian modulus dari loop tes menggunakan
BigDecimal
dannew MathContext(16)
untuk operasi modulus sebagai berikut:Hasil:
sumber
100 trials 94 errors
Anda harus mulai dengan tes yang lulus, dan menunjukkan bahwa memperkenalkan pembulatan akan merusak tes.double
karena tidak ada kesalahan ideone.com/BVCHh3Misalkan Anda punya
kamu bisa menggunakan
BigDecimal
atau tanpa BigDecimal
dengan kedua solusi
d == 9232.13
sumber
RoundingMode.HALF_UP
salah. Cobalah1.505
. Cara yang benar adalah menggunakanBigDecimal.valueOf(d)
.Anda bisa menggunakan kelas DecimalFormat.
sumber
Double.valueOf()
dipilihDouble.parseDouble()
? ThevalueOf()
Metode mengembalikanDouble
objek, sementaraparseDouble()
akan kembalidouble
primitif. Dengan cara kode saat ini ditulis, Anda juga menerapkan auto-unboxing untuk mengembalikannya ke primitif yangtwoDouble
diharapkan oleh variabel Anda , operasi bytecode tambahan. Saya akan mengubah jawaban untuk digunakanparseDouble()
sebagai gantinya.Double.parseDouble()
butuhString
input.Bagaimana Cara Nyata Java memposting solusi ini, yang juga kompatibel untuk versi sebelum Java 1.6.
sumber
sumber
Math.floor(x + 0.5)
danMath.round(x)
@ Milhous: format desimal untuk pembulatan sangat bagus:
Saya akan menambahkan bahwa metode ini sangat baik dalam menyediakan numerik, mekanisme pembulatan aktual - tidak hanya secara visual, tetapi juga saat memproses.
Hipotetis: Anda harus menerapkan mekanisme pembulatan ke dalam program GUI. Untuk mengubah keakuratan / ketepatan hasil keluaran cukup ubah format tanda sisipan (yaitu dalam kurung). Maka:
akan kembali sebagai output:
0.912385
akan kembali sebagai output:
0.91239
akan kembali sebagai output:
0.9124
[EDIT: juga jika format caret seperti itu ("# 0. ############") dan Anda memasukkan desimal, misalnya 3.1415926, demi argumen, DecimalFormat tidak menghasilkan sampah apa pun ( misalnya membuntuti nol) dan akan kembali:
3.1415926
.. jika Anda cenderung. Memang, ini sedikit bertele-tele untuk menyukai beberapa dev - tapi hei, punya jejak memori rendah selama pemrosesan dan sangat mudah untuk diterapkan.]Jadi pada dasarnya, keindahan DecimalFormat adalah bahwa ia secara bersamaan menangani tampilan string - serta tingkat set pembulatan presisi. Ergo: Anda mendapatkan dua manfaat dengan harga satu implementasi kode. ;)
sumber
double
. Gunakan BigDecimal atau format berbasis desimal lainnya.Berikut ini adalah ringkasan dari apa yang dapat Anda gunakan jika Anda ingin hasilnya sebagai String:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Berikut adalah saran perpustakaan apa yang dapat Anda gunakan jika Anda menginginkannya
double
. Saya tidak akan merekomendasikan ini untuk konversi string, karena double mungkin tidak dapat mewakili apa yang Anda inginkan (lihat misalnya di sini ):Presisi dari Apache Commons Math
Fungsi dari Colt
Utils dari Weka
sumber
Anda dapat menggunakan metode utilitas berikut-
sumber
round(1.005,2);
atauround(0.50594724957626620092, 20);
Solusi ringkas:
Lihat juga, https://stackoverflow.com/a/22186845/212950 Terima kasih kepada jpdymond karena menawarkan ini.
sumber
Anda dapat menggunakan BigDecimal
Lihat: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
sumber
Coba ini: org.apache.commons.math3.util.Precision.round (double x, skala int)
Lihat: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Beranda Apache Commons Mathematics Library adalah: http://commons.apache.org/proper/commons-math/index.html
Penerapan internal metode ini adalah:
sumber
Karena saya tidak menemukan jawaban lengkap tentang tema ini, saya telah mengumpulkan sebuah kelas yang harus menangani ini dengan benar, dengan dukungan untuk:
Penggunaannya cukup sederhana :
(Demi contoh ini saya menggunakan lokal kustom)
Ini kelasnya :
sumber
Jika Anda benar-benar ingin angka desimal untuk perhitungan (dan tidak hanya untuk output), jangan gunakan format floating point berbasis biner seperti ganda.
Saya menggunakan BigDecimal untuk perhitungan, tapi ingat itu tergantung pada ukuran angka yang Anda hadapi. Dalam sebagian besar implementasi saya, saya menemukan parsing dari double atau integer ke Long sudah cukup untuk perhitungan angka yang sangat besar.
Bahkan, saya baru-baru ini menggunakan parsed-to-Long untuk mendapatkan representasi yang akurat (sebagai lawan hasil hex) dalam GUI untuk angka sebesar ######################### karakter ################ (sebagai contoh).
sumber
Untuk mencapai ini kita dapat menggunakan formatter ini:
atau:
Gunakan metode ini untuk mendapatkan selalu dua desimal:
Menentukan nilai-nilai ini:
Dengan menggunakan metode ini kita bisa mendapatkan hasil ini:
demo online.
sumber
Hanya dalam kasus seseorang masih membutuhkan bantuan dengan ini. Solusi ini sangat cocok untuk saya.
mengembalikan a
String
dengan output yang diinginkan.sumber
Saya setuju dengan jawaban yang dipilih untuk digunakan
DecimalFormat
--- atau sebagai alternatifBigDecimal
.Silakan baca Pembaruan di bawah ini terlebih dahulu!
Namun jika Anda tidak ingin membulatkan nilai ganda dan mendapatkandouble
hasil nilai, Anda dapat menggunakanorg.apache.commons.math3.util.Precision.round(..)
seperti yang disebutkan di atas. Implementasinya menggunakanBigDecimal
, lambat dan membuat sampah.Metode serupa tetapi cepat dan bebas-sampah disediakan olehDoubleRounder
utilitas di perpustakaan decimal4j:Akan menghasilkan
Lihat https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Penafian: Saya terlibat dalam proyek desimal4j.
Pembaruan: Seperti yang ditunjukkan @iaforek, DoubleRounder terkadang mengembalikan hasil yang berlawanan dengan intuisi. Alasannya adalah bahwa ia melakukan pembulatan yang benar secara matematis. Contohnya
DoubleRounder.round(256.025d, 2)
akan dibulatkan ke 256,02 karena nilai ganda yang direpresentasikan sebagai 256.025d agak lebih kecil dari nilai rasional 256.025 dan karenanya akan dibulatkan ke bawah.Catatan:
BigDecimal(double)
konstruktor (tetapi tidakvalueOf(double)
yang menggunakan konstruktor string).Untuk alasan itu dan semua yang disebutkan di atas dalam posting ini saya tidak bisa merekomendasikan untuk menggunakan DoubleRounder .
sumber
Cuplikan kode di bawah ini menunjukkan cara menampilkan n digit. Caranya adalah dengan mengatur variabel pp ke 1 diikuti oleh n nol. Dalam contoh di bawah ini, nilai pp variabel memiliki 5 nol, sehingga 5 digit akan ditampilkan.
sumber
Jika Anda menggunakan
DecimalFormat
untuk mengkonversidouble
keString
, itu sangat mudah:Ada beberapa
RoundingMode
nilai enum untuk dipilih, tergantung pada perilaku yang Anda butuhkan.sumber
Saya datang ke sini hanya ingin jawaban sederhana tentang cara membulatkan angka. Ini adalah jawaban tambahan untuk memberikan itu.
Cara membulatkan angka di Jawa
Kasus yang paling umum adalah menggunakan
Math.round()
.Bilangan dibulatkan ke bilangan bulat terdekat. Sebuah
.5
nilai dibulatkan. Jika Anda membutuhkan perilaku pembulatan yang berbeda dari itu, Anda bisa menggunakan salah satu fungsi Matematika lainnya . Lihat perbandingan di bawah ini.bulat
Sebagaimana dinyatakan di atas, ini membulatkan ke bilangan bulat terdekat.
.5
desimal ditangkap. Metode ini mengembalikan sebuahint
.langit-langit
Nilai desimal apa pun dibulatkan ke bilangan bulat berikutnya. Pergi ke langit - langit . Metode ini mengembalikan a
double
.lantai
Nilai desimal apa pun dibulatkan ke bilangan bulat berikutnya. Metode ini mengembalikan a
double
.rintis
Ini mirip dengan putaran dalam nilai desimal itu yang bulat ke bilangan bulat terdekat. Namun, tidak seperti
round
,.5
nilai membulatkan ke bilangan bulat genap. Metode ini mengembalikan adouble
.sumber
Jika Anda menggunakan teknologi yang memiliki JDK minimal. Inilah cara tanpa Java libs:
sumber
DecimalFormat adalah cara terbaik untuk menghasilkan, tapi saya tidak suka itu. Saya selalu melakukan ini sepanjang waktu, karena mengembalikan nilai ganda. Jadi saya bisa menggunakannya lebih dari sekedar output.
ATAU
Jika Anda membutuhkan nilai tempat desimal besar, Anda dapat menggunakan BigDecimal sebagai gantinya. Bagaimanapun juga
.0
itu penting. Tanpanya pembulatan 0.33333d5 menghasilkan 0.33333 dan hanya 9 digit yang dibolehkan. Fungsi kedua tanpa.0
memiliki masalah dengan 0,30000 mengembalikan 0,30000000000000004.sumber
inilah jawaban saya:
sumber
Jadi setelah membaca sebagian besar jawaban, saya menyadari sebagian besar dari mereka tidak akan tepat, pada kenyataannya menggunakan
BigDecimal
sepertinya pilihan terbaik, tetapi jika Anda tidak mengerti caraRoundingMode
kerjanya, Anda pasti akan kehilangan presisi. Saya menemukan ini ketika bekerja dengan angka-angka besar dalam sebuah proyek dan berpikir itu bisa membantu orang lain mengalami kesulitan dalam mengumpulkan angka. Sebagai contoh.Anda akan mengharapkan untuk mendapatkan
1363.28
sebagai output, tetapi Anda akan berakhir dengan1363.27
, yang tidak diharapkan, jika Anda tidak tahu apa yangRoundingMode
dilakukannya. Jadi melihat ke dalam Oracle Docs , Anda akan menemukan deskripsi berikut untukRoundingMode.HALF_UP
.Jadi mengetahui ini, kami menyadari bahwa kami tidak akan mendapatkan pembulatan yang tepat, kecuali jika kami ingin berputar ke arah tetangga terdekat . Jadi, untuk mencapai putaran yang memadai, kita perlu mengulang dari angka
n-1
desimal ke angka desimal yang diinginkan. Sebagai contoh.Ini pada akhirnya akan memberi kita hasil yang diharapkan, yang akan menjadi
1363.28
.sumber
Di mana dp = tempat desimal yang Anda inginkan, dan nilainya dua kali lipat.
sumber
1.0
untukvalue = 1.005
dandp = 2
. Gunakan ini sebagai gantinya.Perlu diingat bahwa String.format () dan DecimalFormat menghasilkan string menggunakan Lokal default. Jadi mereka dapat menulis angka yang diformat dengan titik atau koma sebagai pemisah antara bagian integer dan desimal. Untuk memastikan bahwa String bulat dalam format yang Anda inginkan, gunakan java.text.NumberFormat seperti itu:
Akan mencetak dalam bahasa Inggris lokal (tidak peduli apa lokal Anda): 0.99 123.57 123.00
Contoh ini diambil dari Farenda - cara mengkonversi ganda ke String dengan benar .
sumber
Secara umum, pembulatan dilakukan dengan penskalaan:
round(num / p) * p
sumber