Saya dapat menyebutkan tiga keuntungan menggunakan double
(atau float
) alih-alih decimal
:
- Menggunakan lebih sedikit memori.
- Lebih cepat karena operasi matematika floating point secara asli didukung oleh prosesor.
- Dapat mewakili rentang angka yang lebih besar.
Tetapi keuntungan ini tampaknya hanya berlaku untuk operasi perhitungan yang intensif, seperti yang ditemukan dalam perangkat lunak pemodelan. Tentu saja, ganda tidak boleh digunakan ketika presisi dibutuhkan, seperti perhitungan keuangan. Jadi, adakah alasan praktis untuk memilih double
(atau float
) alih-alih decimal
dalam aplikasi "normal"?
Diedit untuk menambahkan: Terima kasih atas semua tanggapan hebat, saya belajar dari mereka.
Satu pertanyaan lebih lanjut: Beberapa orang menyatakan bahwa ganda dapat lebih tepatnya mewakili bilangan real. Ketika dideklarasikan, saya akan berpikir bahwa mereka biasanya mewakili mereka dengan lebih akurat. Tetapi apakah benar pernyataan bahwa keakuratan dapat menurun (kadang-kadang secara signifikan) ketika operasi floating point dilakukan?
Jawaban:
Saya pikir Anda sudah merangkum keuntungan dengan cukup baik. Namun Anda kehilangan satu poin. The
decimal
jenis ini hanya lebih akurat di mewakili basis 10 angka (misalnya yang digunakan dalam mata uang / perhitungan keuangan). Secara umum,double
jenis ini akan menawarkan setidaknya sebagai presisi besar (seseorang mengoreksi saya jika saya salah) dan pasti kecepatan yang lebih besar untuk bilangan real arbitrer. Kesimpulan sederhananya adalah: ketika mempertimbangkan mana yang akan digunakan, selalu gunakandouble
kecuali Anda membutuhkanbase 10
akurasi yangdecimal
menawarkan.Edit:
Mengenai pertanyaan tambahan Anda tentang penurunan akurasi angka floating-point setelah operasi, ini adalah masalah yang sedikit lebih halus. Memang, presisi (saya menggunakan istilah yang dipertukarkan untuk keakuratan di sini) akan terus menurun setelah setiap operasi dilakukan. Ini karena dua alasan:
Dalam semua kasus, jika Anda ingin membandingkan dua angka floating-point yang seharusnya secara teori setara (tetapi diterima dengan menggunakan perhitungan yang berbeda), Anda perlu mengizinkan tingkat toleransi tertentu (berapa banyak bervariasi, tetapi biasanya sangat kecil) .
Untuk tinjauan umum yang lebih rinci tentang kasus-kasus tertentu di mana kesalahan dalam akurasi dapat diperkenalkan, lihat bagian Akurasi artikel Wikipedia . Akhirnya, jika Anda menginginkan diskusi yang serius (dan matematis) tentang angka / operasi floating-point di tingkat mesin, coba baca artikel yang sering dikutip Apa Yang Harus Diketahui Setiap Ilmuwan Komputer Tentang Aritmatika Titik Apung .
sumber
double
. Komputer modern masih akan mencetak nilai yang benar tetapi hanya karena mereka "menebak" hasilnya - bukan karena itu benar-benar diungkapkan dengan benar.Decimal
jenis memiliki 93-bit presisi dalam mantissa, dibandingkan dengan sekitar 52 untukdouble
. Saya berharap Microsoft mendukung format IEEE 80-bit, walaupun itu harus diisi hingga 16 byte; itu akan memungkinkan jangkauan yang lebih besar daripadadouble
atauDecimal
, kecepatan yang jauh lebih baik daripadaDecimal
, dukungan untuk operasi transendental (misalnya sin (x), log (x), dll), dan presisi yang sementara tidak sebagusDecimal
akan jauh lebih baik daripadadouble
.Anda tampaknya cocok dengan manfaat menggunakan tipe floating point. Saya cenderung mendesain desimal dalam semua kasus, dan mengandalkan profiler untuk memberi tahu saya jika operasi pada desimal menyebabkan kemacetan atau perlambatan. Dalam kasus-kasus itu, saya akan "menurunkan casting" menjadi dua kali lipat atau mengambang, tetapi hanya melakukannya secara internal, dan dengan hati-hati mencoba mengelola kehilangan presisi dengan membatasi jumlah digit signifikan dalam operasi matematika yang sedang dilakukan.
Secara umum, jika nilai Anda bersifat sementara (tidak digunakan kembali), Anda aman untuk menggunakan tipe floating point. Masalah sebenarnya dengan tipe floating point adalah tiga skenario berikut.
123456789.1 * .000000000000000987654321
)EDIT
Menurut dokumentasi referensi pada desimal C # :
Jadi untuk memperjelas pernyataan saya di atas:
Saya hanya pernah bekerja di industri di mana desimal menguntungkan. Jika Anda bekerja pada mesin phsyics atau grafis, mungkin jauh lebih bermanfaat untuk mendesain tipe floating point (float atau double).
Desimal tidak akurat tanpa batas (tidak mungkin untuk merepresentasikan ketelitian tak terbatas untuk non-integral dalam tipe data primitif), tetapi desimal jauh lebih tepat daripada ganda:
EDIT 2
Menanggapi komentar Konrad Rudolph , item # 1 (di atas) sudah pasti benar. Agregasi ketidaktepatan memang bertambah. Lihat kode di bawah ini untuk contoh:
Ini menghasilkan sebagai berikut:
Seperti yang Anda lihat, meskipun kami menambahkan dari konstanta sumber yang sama, hasil dari gandanya kurang tepat (meskipun mungkin akan membulat dengan benar), dan float jauh lebih tidak tepat, ke titik di mana ia telah direduksi menjadi hanya dua digit signifikan.
sumber
Single: 667660.400000000000
sedangkan nilai desimal dihasilkanDecimal: 666666.7000000000
. Nilai float sedikit kurang dari seribu di atas nilai yang benar.Gunakan desimal untuk nilai basis 10, mis. Perhitungan keuangan, seperti yang disarankan orang lain.
Tapi ganda umumnya lebih akurat untuk nilai-nilai yang dihitung sewenang-wenang.
Misalnya, jika Anda ingin menghitung bobot setiap baris dalam portofolio, gunakan gandakan karena hasilnya akan hampir mencapai 100%.
Dalam contoh berikut, doubleResult lebih dekat ke 1 daripada desimalResult:
Jadi sekali lagi mengambil contoh portofolio:
Nilai pasar dari setiap baris dalam portofolio adalah nilai moneter dan mungkin akan digambarkan sebagai desimal.
Bobot masing-masing garis dalam portofolio (= Nilai Pasar / SUM (Nilai Pasar)) biasanya lebih baik dinyatakan sebagai dua kali lipat.
sumber
Gunakan dobel atau pelampung ketika Anda tidak membutuhkan ketepatan, misalnya, dalam permainan platformer yang saya tulis, saya menggunakan pelampung untuk menyimpan kecepatan pemain. Jelas saya tidak perlu ketepatan super di sini karena saya akhirnya membulatkan ke Int untuk menggambar di layar.
sumber
Dalam beberapa Akuntansi, pertimbangkan kemungkinan menggunakan tipe integral sebagai gantinya atau bersamaan. Misalnya, katakan bahwa aturan yang Anda operasikan mengharuskan setiap hasil perhitungan diteruskan dengan setidaknya 6 desimal dan hasil akhir akan dibulatkan ke sen terdekat.
Perhitungan 1/6 dari $ 100 menghasilkan $ 16.66666666666666 ..., sehingga nilai yang dilakukan dalam lembar kerja adalah $ 16.666667. Baik ganda dan desimal harus menghasilkan hasil yang akurat ke 6 tempat desimal. Namun, kita dapat menghindari kesalahan kumulatif dengan membawa hasil ke depan sebagai bilangan bulat 16666667. Setiap perhitungan selanjutnya dapat dilakukan dengan presisi yang sama dan diteruskan dengan cara yang sama. Melanjutkan contoh, saya menghitung pajak penjualan Texas pada jumlah itu (16666667 * .0825 = 1375000). Menambahkan dua (itu adalah lembar kerja pendek) 1666667 + 1375000 = 18041667. Memindahkan titik desimal kembali memberi kita 18,041667, atau $ 18,04.
Meskipun contoh singkat ini tidak akan menghasilkan kesalahan kumulatif menggunakan dobel atau desimal, cukup mudah untuk menunjukkan kasus di mana hanya menghitung dobel atau desimal dan meneruskan akan menumpuk kesalahan yang signifikan. Jika aturan yang Anda operasikan memerlukan sejumlah tempat desimal, simpan setiap nilai sebagai bilangan bulat dengan mengalikan 10 ^ (diperlukan # tempat desimal), dan kemudian bagi dengan 10 ^ (diperlukan # tempat desimal) untuk mendapatkan yang sebenarnya nilai akan menghindari kesalahan kumulatif.
Dalam situasi di mana pecahan uang tidak terjadi (misalnya, mesin penjual otomatis), tidak ada alasan untuk menggunakan jenis yang tidak terpisahkan sama sekali. Anggap saja sebagai menghitung uang, bukan dolar. Saya telah melihat kode di mana setiap perhitungan hanya melibatkan seluruh uang, namun penggunaan ganda menyebabkan kesalahan! Matematika integer saja menghapus masalah. Jadi, jawaban saya yang tidak konvensional adalah, jika mungkin, lupakan dobel dan desimal.
sumber
Jika Anda perlu melakukan binary interrop dengan bahasa atau platform lain, maka Anda mungkin perlu menggunakan float atau double, yang terstandarisasi.
sumber
Catatan: posting ini didasarkan pada informasi kemampuan tipe desimal dari http://csharpindepth.com/Articles/General/Decimal.aspx dan interpretasi saya sendiri tentang apa artinya itu. Saya akan menganggap ganda adalah presisi ganda normal IEEE.
Note2: terkecil dan terbesar di pos ini merujuk pada besarnya angka.
Pro "desimal".
Kontra desimal
Pendapat saya adalah bahwa Anda harus menggunakan "desimal" untuk pekerjaan uang dan kasus lain di mana pencocokan perhitungan manusia sangat penting dan Anda harus menggunakan penggunaan ganda sebagai pilihan default Anda sepanjang waktu.
sumber
Tergantung pada apa yang Anda butuhkan.
Karena float dan double tipe data biner Anda memiliki beberapa diifculties dan errrors di dalam angka bulat, jadi misalnya double akan bulat 0,1 hingga 0,100000001490116, ganda juga akan bulat 1/3 hingga 0,33333334326441. Sederhananya tidak semua bilangan real memiliki representasi akurat dalam tipe ganda
Untungnya C # juga mendukung apa yang disebut aritmatika titik-mengambang desimal, di mana angka-angka diwakili melalui sistem numerik desimal daripada sistem biner. Dengan demikian, aritmetika floating point desimal tidak kehilangan keakuratan saat menyimpan dan memproses angka floating-point. Ini membuatnya sangat cocok untuk perhitungan di mana tingkat akurasi yang tinggi diperlukan.
sumber
Gunakan floating point jika Anda menghargai kinerja melebihi kebenaran.
sumber
Pilih jenis fungsi aplikasi Anda. Jika Anda membutuhkan ketelitian seperti dalam analisis keuangan, Anda telah menjawab pertanyaan Anda. Tetapi jika aplikasi Anda dapat menyelesaikan dengan estimasi Anda ok dengan ganda.
Apakah aplikasi Anda membutuhkan perhitungan cepat atau akankah ia punya waktu di dunia untuk memberi Anda jawaban? Itu benar-benar tergantung pada jenis aplikasi.
Grafis lapar? float atau double sudah cukup. Analisis data keuangan, meteor yang menyerang planet semacam presisi? Mereka akan membutuhkan sedikit presisi :)
sumber
Desimal memiliki byte yang lebih luas, dobel didukung oleh CPU. Desimal adalah basis-10, jadi konversi desimal ke dua terjadi saat desimal dihitung.
Perlu diingat. NET CLR hanya mendukung Math.Pow (double, double). Desimal tidak didukung.
.NET Framework 4
sumber
Nilai ganda akan bersambung ke notasi ilmiah secara default jika notasi itu lebih pendek dari tampilan desimal. (mis. 0,00000003 akan menjadi 3e-8) Nilai desimal tidak akan pernah bersambung ke notasi ilmiah. Ketika membuat serial untuk dikonsumsi oleh pihak eksternal, ini mungkin menjadi pertimbangan.
sumber