Perbedaan besar
Sesuai namanya, a double
memiliki 2x presisi [1] . Secara umum a memiliki 15 digit desimal presisi, sementarafloat
double
float
memiliki 7.
Begini cara menghitung jumlah digit:
double
memiliki 52 mantissa bit + 1 bit tersembunyi: log (2 53 ) ÷ log (10) = 15,95 digit
float
memiliki 23 bit mantissa + 1 bit tersembunyi: log (2 24 ) ÷ log (10) = 7.22 digit
Kehilangan presisi ini dapat menyebabkan kesalahan pemotongan yang lebih besar terakumulasi ketika perhitungan berulang dilakukan, misalnya
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
sementara
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
Juga, nilai maksimum float adalah tentang 3e38
, tetapi dua kali lipat adalah tentang 1.7e308
, jadi menggunakan float
dapat menekan "tak terbatas" (yaitu angka floating-point khusus) lebih mudah daripadadouble
untuk sesuatu yang sederhana, misalnya menghitung faktorial 60.
Selama pengujian, mungkin beberapa kasus uji berisi angka besar ini, yang dapat menyebabkan program Anda gagal jika Anda menggunakan pelampung.
Tentu saja, kadang-kadang, bahkan double
tidak cukup akurat, maka kita kadang-kadang memiliki long double
[1] (contoh di atas memberikan 9,00000000000000000066 pada Mac), tetapi semua tipe floating point menderita kesalahan pembulatan , jadi jika presisi sangat penting (misalnya uang) pemrosesan) Anda harus menggunakan int
atau kelas pecahan.
Selain itu, jangan gunakan +=
untuk menjumlahkan banyak angka floating point, karena kesalahan menumpuk dengan cepat. Jika Anda menggunakan Python, gunakan fsum
. Jika tidak, cobalah untuk mengimplementasikan algoritma penjumlahan Kahan .
[1]: Standar C dan C ++ tidak menentukan representasi float
, double
dan long double
. Ada kemungkinan bahwa ketiganya diimplementasikan sebagai presisi ganda IEEE. Namun demikian, untuk sebagian besar arsitektur (gcc, MSVC; x86, x64, ARM) float
adalah memang IEEE presisi tunggal floating point nomor (binary32), dan double
merupakan sebuah IEEE double-presisi floating point nomor (binary64).
Berikut adalah apa yang dikatakan standar C99 (ISO-IEC 9899 6.2.5 §10) atau C ++ 2003 (ISO-IEC 14882-2003 3.1.9 §8):
Standar C ++ menambahkan:
Saya akan menyarankan untuk melihat pada apa yang Harus Tahu Setiap Ilmuwan Komputer Tentang Aritmatika Floating-Point yang mencakup standar IEEE floating-point secara mendalam. Anda akan belajar tentang detail representasi dan Anda akan menyadari ada tradeoff antara besarnya dan presisi. Ketepatan representasi titik apung meningkat dengan besarnya berkurang, karenanya angka titik apung antara -1 dan 1 adalah yang paling presisi.
sumber
Diberikan persamaan kuadrat: x 2 - 4.0000000 x + 3.9999999 = 0, akar yang tepat untuk 10 digit signifikan adalah, r 1 = 2.000316228 dan r 2 = 1.999683772.
Dengan menggunakan
float
dandouble
, kita dapat menulis program pengujian:Menjalankan program memberi saya:
Perhatikan bahwa jumlahnya tidak besar, tetapi Anda tetap mendapatkan efek pembatalan menggunakan
float
.(Pada kenyataannya, di atas bukan cara terbaik untuk memecahkan persamaan kuadratik menggunakan angka floating-point presisi tunggal atau ganda, tetapi jawabannya tetap tidak berubah bahkan jika seseorang menggunakan metode yang lebih stabil .)
sumber
sumber
Ukuran angka yang terlibat dalam perhitungan float-point bukanlah hal yang paling relevan. Ini perhitungan yang sedang dilakukan yang relevan.
Intinya, jika Anda melakukan perhitungan dan hasilnya adalah bilangan irasional atau desimal berulang, maka akan ada kesalahan pembulatan ketika angka itu dimasukkan ke dalam struktur data ukuran terbatas yang Anda gunakan. Karena double adalah dua kali ukuran float maka kesalahan pembulatan akan jauh lebih kecil.
Tes dapat secara khusus menggunakan angka yang akan menyebabkan kesalahan semacam ini dan karenanya diuji bahwa Anda telah menggunakan jenis yang sesuai dalam kode Anda.
sumber
Tipe float, panjang 32 bit, memiliki ketepatan 7 digit. Meskipun dapat menyimpan nilai dengan rentang yang sangat besar atau sangat kecil (+/- 3.4 * 10 ^ 38 atau * 10 ^ -38), ia hanya memiliki 7 digit signifikan.
Ketik ganda, panjang 64 bit, memiliki jangkauan lebih besar (* 10 ^ + / - 308) dan presisi 15 digit.
Tipe long double secara nominal 80 bit, meskipun pasangan kompiler / OS yang diberikan dapat menyimpannya sebagai 12-16 byte untuk tujuan perataan. Double panjang memiliki eksponen yang luar biasa besar dan memiliki presisi 19 digit. Microsoft, dalam kebijaksanaan mereka yang tak terbatas, membatasi panjang ganda hingga 8 byte, sama dengan ganda biasa.
Secara umum, cukup gunakan tipe ganda ketika Anda membutuhkan nilai / variabel floating point. Nilai floating point literal yang digunakan dalam ekspresi akan diperlakukan sebagai ganda secara default, dan sebagian besar fungsi matematika yang mengembalikan nilai floating point mengembalikan ganda. Anda akan menghemat banyak sakit kepala dan typecasting jika Anda hanya menggunakan ganda.
sumber
Saya hanya mengalami kesalahan yang membutuhkan waktu lama untuk mencari tahu dan berpotensi memberikan Anda contoh presisi mengambang yang baik.
Outputnya adalah
Seperti yang Anda lihat setelah 0,83, presisi menurun secara signifikan.
Namun, jika saya atur
t
dua kali lipat, masalah seperti itu tidak akan terjadi.Butuh waktu lima jam untuk menyadari kesalahan kecil ini, yang merusak program saya.
sumber
double
bukanlah solusi yang baik di sini. Anda menggunakanint
untuk menghitung dan melakukan perkalian internal untuk mendapatkan nilai floating-point Anda.Mengapung memiliki presisi kurang dari dua kali lipat. Meskipun Anda sudah tahu, bacalah Apa yang Harus Kita Ketahui Tentang Aritmatika Titik Apung untuk pemahaman yang lebih baik.
sumber
Saat menggunakan angka floating point Anda tidak dapat mempercayai bahwa tes lokal Anda akan persis sama dengan tes yang dilakukan di sisi server. Lingkungan dan kompiler mungkin berbeda pada sistem lokal Anda dan di mana tes akhir dijalankan. Saya telah melihat masalah ini beberapa kali sebelumnya di beberapa kompetisi TopCoder terutama jika Anda mencoba membandingkan dua angka floating point.
sumber
Operasi perbandingan bawaan berbeda seperti ketika Anda membandingkan 2 angka dengan titik mengambang, perbedaan dalam tipe data (yaitu float atau double) dapat menghasilkan hasil yang berbeda.
sumber
Jika seseorang bekerja dengan pemrosesan tertanam, pada akhirnya perangkat keras yang mendasarinya (misalnya FPGA atau model prosesor / mikrokontroler tertentu) akan mengapung diimplementasikan secara optimal dalam perangkat keras sedangkan ganda akan menggunakan rutin perangkat lunak. Jadi, jika presisi float cukup untuk menangani kebutuhan, program akan mengeksekusi beberapa kali lebih cepat dengan float kemudian berlipat ganda. Seperti dicatat pada jawaban lain, waspadalah terhadap kesalahan akumulasi.
sumber
Tidak seperti
int
(bilangan bulat), afloat
memiliki titik desimal, dan begitu juga adouble
. Tetapi perbedaan antara keduanya adalah bahwadouble
dua kali lebih detail dari afloat
, artinya dapat memiliki dua kali lipat jumlah angka setelah titik desimal.sumber