Jadi saya memiliki himpunan ganda sama dengan 1234, saya ingin memindahkan tempat desimal menjadi 12,34
Jadi untuk melakukan ini saya mengalikan 0,1 sampai 1234 dua kali, seperti ini
double x = 1234;
for(int i=1;i<=2;i++)
{
x = x*.1;
}
System.out.println(x);
Ini akan mencetak hasilnya, "12.340000000000002"
Adakah cara, tanpa hanya memformatnya menjadi dua tempat desimal, agar penyimpanan ganda 12,34 benar?
x /= 100;
?Jawaban:
Jika Anda menggunakan
double
ataufloat
, Anda harus menggunakan pembulatan atau akan melihat beberapa kesalahan pembulatan. Jika Anda tidak dapat melakukan ini, gunakanBigDecimal
.Masalah yang Anda hadapi adalah bahwa 0,1 bukanlah representasi yang tepat, dan dengan melakukan kalkulasi dua kali, Anda menambah kesalahan itu.
Namun, 100 dapat direpresentasikan secara akurat, jadi cobalah:
yang mencetak:
Ini berfungsi karena
Double.toString(d)
melakukan sejumlah kecil pembulatan atas nama Anda, tetapi tidak banyak. Jika Anda bertanya-tanya bagaimana tampilannya tanpa pembulatan:cetakan:
Singkatnya, pembulatan tidak dapat dihindari untuk jawaban yang masuk akal dalam floating point apakah Anda melakukannya secara eksplisit atau tidak.
Catatan:
x / 100
danx * 0.01
tidak persis sama dalam hal kesalahan pembulatan. Ini karena kesalahan putaran untuk ekspresi pertama bergantung pada nilai x, sedangkan0.01
kesalahan putaran kedua memiliki kesalahan putaran tetap.cetakan
sumber
1234/100
, seperti yang telah Anda lakukan, tidak benar-benar melakukan apa pun tentang masalah yang mendasarinya - itu harus sama persis dengan menulis1234 * 0.01
./100
dan*0.01
setara satu sama lain, tetapi tidak dengan OP*0.1*0.1
.Tidak - jika Anda ingin menyimpan nilai desimal secara akurat, gunakan
BigDecimal
.double
tidak dapat mewakili angka seperti 0,1 dengan tepat, sama seperti Anda dapat menulis nilai sepertiga persis dengan jumlah digit desimal yang terbatas.sumber
jika itu hanya pemformatan, coba printf
keluaran
sumber
System.out.printf()
juga cara yang tepat untuk melakukannya.Dalam perangkat lunak keuangan, umum menggunakan bilangan bulat untuk uang. Di sekolah, kami diajari cara menggunakan fixed-point alih-alih floating, tapi itu biasanya kekuatan dua. Menyimpan uang dalam bilangan bulat bisa disebut "titik tetap" juga.
Di kelas, kami ditanyai secara umum angka apa yang bisa direpresentasikan dengan tepat dalam basis.
Untuk
base=p1^n1*p2^n2
... Anda dapat mewakili N apa pun di mana N = n * p1 ^ m1 * p2 ^ m2.Misalkan
base=14=2^1*7^1
... Anda dapat mewakili 1/7 1/14 1/28 1/49 tetapi tidak 1/3Saya tahu tentang perangkat lunak keuangan - Saya mengubah laporan keuangan Ticketmaster dari VAX asm menjadi PASCAL. Mereka memiliki formatln () sendiri dengan kode untuk uang. Alasan untuk konversi adalah 32 bit integer tidak lagi cukup. +/- 2 miliar sen adalah $ 20 juta dan itu melimpah untuk Piala Dunia atau Olimpiade, saya lupa.
Saya disumpah untuk merahasiakan. Baiklah. Di akademi, jika ada baiknya Anda mempublikasikan; dalam industri, Anda merahasiakannya.
sumber
Anda dapat mencoba representasi bilangan bulat
sumber
r
kurang dari 10, tidak ada bantalan 0 yang terjadi dan 1204 akan menghasilkan hasil 12,4. String pemformatan yang benar lebih mirip dengan "% d.% 02d"Ini disebabkan oleh cara komputer menyimpan bilangan floating-point. Mereka tidak melakukannya dengan tepat. Sebagai seorang programmer, Anda harus membaca panduan floating-point ini untuk membiasakan diri dengan cobaan dan kesengsaraan dalam menangani bilangan floating-point.
sumber
Lucu bahwa banyak posting menyebutkan untuk menggunakan BigDecimal tetapi tidak ada yang mau memberikan jawaban yang benar berdasarkan BigDecimal? Karena bahkan dengan BigDecimal, Anda masih bisa salah, seperti yang ditunjukkan oleh kode ini
Memberikan keluaran ini
Konstruktor BigDecimal secara khusus menyebutkan bahwa lebih baik menggunakan konstruktor String daripada konstruktor numerik. Presisi tertinggi juga dipengaruhi oleh MathContext opsional.
Menurut Javadoc BigDecimal dimungkinkan untuk membuat BigDecimal yang sama persis dengan 0.1, asalkan Anda menggunakan konstruktor String.
sumber
Ya ada. Dengan setiap operasi ganda Anda mungkin kehilangan akurasi tetapi jumlah akurasi berbeda untuk setiap operasi dan dapat diminimalkan dengan memilih urutan operasi yang tepat. Misalnya saat mengalikan kumpulan bilangan, yang terbaik adalah mengurutkan himpunan berdasarkan eksponen sebelum mengalikan.
Setiap buku yang layak tentang angka-angka menggambarkan hal ini. Misalnya: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Dan untuk menjawab pertanyaan Anda:
Gunakan pembagian, bukan perkalian, dengan cara ini Anda mendapatkan hasil yang benar.
sumber
Tidak, karena tipe floating point Java (memang semua tipe floating point) adalah trade-off antara ukuran dan presisi. Meskipun sangat berguna untuk banyak tugas, jika Anda membutuhkan ketepatan yang sewenang-wenang, Anda harus menggunakannya
BigDecimal
.sumber