presisi 'float' vs 'double'

155

Kode

float x  = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);

akan memberi Anda output

x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116

dimana pada baris ketiga 741012573242adalah sampah dan pada baris keempat 116adalah sampah. Apakah ganda selalu memiliki 16 angka signifikan sedangkan float selalu memiliki 7 angka signifikan? Mengapa ganda tidak memiliki 14 angka penting?

foo
sumber

Jawaban:

146

Nomor titik apung di C menggunakan pengkodean IEEE 754 .

Jenis pengkodean ini menggunakan tanda, signifikansi, dan eksponen.

Karena penyandian ini, banyak angka akan memiliki perubahan kecil untuk memungkinkannya disimpan.

Juga, jumlah digit signifikan dapat berubah sedikit karena itu adalah representasi biner, bukan angka desimal.

Presisi tunggal (float) memberi Anda 23 bit signifikan, 8 bit eksponen, dan 1 bit tanda.

Presisi ganda (ganda) memberi Anda 52 bit signifikan, 11 bit eksponen, dan 1 bit tanda.

Alan Geleynse
sumber
4
C99 tidak, sebelumnya terserah kompiler.
Alan Geleynse
21
-1 Pernyataan ini sangat salah: "Karena penyandian ini, Anda tidak pernah dapat menjamin bahwa Anda tidak akan memiliki perubahan nilai Anda."
R .. GitHub BERHENTI MEMBANTU ICE
16
@Lan: C99 tidak memerlukan IEEE floating point; itu hanya merekomendasikannya.
R .. GitHub BERHENTI MEMBANTU ICE
4
@Lan: R .. benar; Lampiran F (yang menentukan ikatan IEEE-754) adalah normatif, tetapi hanya berlaku jika suatu implementasi menentukan __STDC_IEC_559__. Implementasi yang tidak mendefinisikan bahwa makro bebas untuk tidak sesuai dengan IEEE-754.
Stephen Canon
12
@Alan: Di bawah IEEE 754, itu mudah dijamin bahwa tidak ada perubahan dalam nilai-nilai 0.5, 0.046875atau 0.376739501953125dibandingkan representasi desimal mereka. (Ini semua adalah rasional diadic dengan pembilang pas di mantissa dan basis-2 logaritma penyebut pas di eksponen.)
R .. GitHub BERHENTI MEMBANTU ICE
42

Apakah ganda selalu memiliki 16 angka signifikan sedangkan float selalu memiliki 7 angka signifikan?

Tidak. Doubles selalu memiliki 53 bit signifikan dan float selalu memiliki 24 bit signifikan (kecuali untuk denormals, infinities, dan nilai NaN, tetapi itu adalah subjek untuk pertanyaan yang berbeda). Ini adalah format biner, dan Anda hanya dapat berbicara dengan jelas tentang ketepatan representasi mereka dalam hal angka biner (bit).

Ini analog dengan pertanyaan tentang berapa digit yang dapat disimpan dalam bilangan bulat biner: bilangan bulat 32 bit yang tidak ditandatangani dapat menyimpan bilangan bulat hingga 32 bit, yang tidak secara tepat memetakan ke sejumlah angka desimal: semua bilangan bulat hingga 9 digit desimal dapat disimpan, tetapi banyak nomor 10 digit dapat disimpan juga.

Mengapa ganda tidak memiliki 14 angka penting?

Pengkodean ganda menggunakan 64 bit (1 bit untuk tanda, 11 bit untuk eksponen, 52 bit signifikan eksplisit dan satu bit implisit), yang dua kali lipat jumlah bit yang digunakan untuk mewakili float (32 bit).

Stephen Canon
sumber
15

float: 23 bit signifikan, 8 bit eksponen, dan 1 bit tanda.

ganda: 52 bit signifikansi, 11 bit eksponen, dan 1 bit tanda.

abe312
sumber
11

Biasanya didasarkan pada angka signifikan eksponen dan signifikansi pada basis 2, bukan basis 10. Dari apa yang dapat saya katakan dalam standar C99, bagaimanapun, tidak ada presisi yang ditentukan untuk mengapung dan ganda (selain fakta bahwa 1 dan 1 + 1E-5/ 1 + 1E-7dapat dibedakan [ floatdandouble berulang]). Namun, jumlah angka signifikan diserahkan kepada pelaksana (serta basis mana yang mereka gunakan secara internal, sehingga dengan kata lain, suatu implementasi dapat memutuskan untuk membuatnya berdasarkan pada 18 digit presisi pada basis 3). [1]

Jika Anda perlu mengetahui nilai-nilai ini, konstanta FLT_RADIXdan FLT_MANT_DIG(dan DBL_MANT_DIG/ LDBL_MANT_DIG) didefinisikan dalam float.h.

Alasan itu disebut a doubleadalah karena jumlah byte yang digunakan untuk menyimpannya adalah dua kali lipat jumlah float (tetapi ini termasuk eksponen dan signifikansi). Standar IEEE 754 (digunakan oleh kebanyakan kompiler) mengalokasikan bit relatif lebih banyak untuk signifikansi daripada eksponen (23 hingga 9 untuk floatvs 52 hingga 12 untukdouble ), itulah mengapa presisi lebih dari dua kali lipat.

1: Bagian 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )

pengguna470379
sumber
Salah ketik? C89 membutuhkan epsilon paling banyak 1E-9untuk double, bukan 1E-7.
Rufflewind
10

Pelampung memiliki 23 bit presisi, dan ganda memiliki 52.

Chris Nash
sumber
Detail: binary64 memiliki signifikansi 53 bit (52 disimpan secara eksplisit) binary32 memiliki 24 bit (23 disimpan secara eksplisit).
chux - Reinstate Monica
4

Ini bukan presisi ganda karena bagaimana IEEE 754 , dan karena biner tidak benar-benar menerjemahkan dengan baik ke desimal. Lihatlah standar jika Anda tertarik.

pengguna541686
sumber
4

float adalah singkatan dari floating point number. Di C, tipe data float digunakan dalam kasus-kasus di mana ketepatan jumlah total digit adalah 7.Untuk misalnya: - desimal no. 12.3546987 tidak dapat disimpan dalam float karena memiliki total 9 digit. Output akan ditampilkan sebagai 12.354699 yaitu 7 digit pertama akan ditampilkan seperti yang dimasukkan dalam input dan digit ke-8 akan dibulatkan. Tipe float dapat mewakili nilai mulai dari sekitar 1,5 x 10 ^ (- 45) hingga 3,4 x 10 ^ (38). Dalam hal alokasi memori, float adalah tipe data titik mengambang 32-bit presisi tunggal.

Tidak seperti float, double memiliki presisi 15 hingga 16 digit. Kisaran double adalah 5,0 × 10 ^ (- 345) hingga 1,7 × 10 ^ (308). Dalam hal alokasi byte, ganda adalah data floating point 64-bit Tipe.

Masalah muncul dalam penggunaannya. Float atau double tidak mempengaruhi printf tetapi dalam kasus scanf tipe data yang sesuai akan digunakan tergantung pada jumlah total. digit di no mengambang. itu harus dibaca dari input.

Oleh karena itu ganda lebih disukai daripada float untuk akurasi data yang lebih tinggi.

Semoga ini membantu.

Vineeth Krishna K
sumber