Mengapa% f mencetak nilai besar ketika konstanta floating point dilewatkan sebagai ganti variabel?

9

Dalam program yang diberikan mengapa saya mendapatkan hasil yang berbeda untuk masing-masing printf?

#include <stdio.h>
int main()
{
    float c = 4.4e10;
    printf("%f\n", c);
    printf("%f\n", 4.4e10);
    return 0;
}

Dan itu menunjukkan output berikut:

44000002048.000000
44000000000.000000
pengguna10056563
sumber
4
Jawaban sejauh ini menjelaskan bahwa 4.4e10adalah doublekonstanta yang dikonversi ke floatdalam inisialisasi ctetapi disimpan sebagai doubleketika diteruskan printf. Namun, Anda mungkin juga ingin tahu bahwa menambahkan fakhiran membuatnya menjadi floatkonstan: Percetakan 4.4e10fakan menunjukkan nilai yang sama bahwa hasil dari inisialisasi cke 4.4e10f. floatKonstanta yang membedakan dari doublekonstanta bisa penting untuk melakukan pekerjaan yang berkualitas dengan aritmatika titik-mengambang.
Eric Postpischil
Apakah metode konversi ini bernama apa saja? Saya ingin membacanya.
user10056563
Apakah Anda ingin tahu kapan konversi dari doubleke floatterjadi dalam bahasa C? Atau Anda ingin tahu nilai apa yang dihasilkan dari konversi, yaitu, apa pengaruh konversi itu? Atau sesuatu yang lain?
Eric Postpischil
Saya mempertanyakan tidak balasan di sini atau standar tapi, ketika saya masih muda dan belajar Ckita digunakan printf("%f",x)untuk floatdan printf("%lf",x)untuk double. Kapan semuanya berubah? Dan bagaimana orang akan secara eksplisit mencetak (tunggal) float- printf("%hf",x)??
Adrian Mole
2
@Adrian %lfdi printf adalah hal yang sama dengan %f. A floatdalam argumen variabel dikonversikan menjadi doubleoleh kompiler, sama seperti yang shortdikonversi menjadi int.
SS Anne

Jawaban:

9

A floatadalah tipe yang memegang angka floating point 32-bit, sedangkan konstanta 4.4e10merepresentasikan a double, yang memegang nomor floating point 64-bit (yaitu angka floating point double -precision)

Ketika Anda menetapkan 4.4e10untuk c, nilai 4.4e10tidak dapat direpresentasikan secara tepat (kesalahan pembulatan dalam parameter yang disebut mantissa), dan nilai terdekat yang mungkin (44000002048) disimpan. Ketika diteruskan ke printf, itu dipromosikan kembali ke double, termasuk kesalahan pembulatan.

Dalam kasus kedua, nilainya adalah doublesepanjang waktu, tanpa penyempitan dan pelebaran, dan ini merupakan kasus bahwa a doubledapat mewakili nilai dengan tepat.

Jika ini adalah perilaku yang tidak diinginkan, Anda dapat mendeklarasikan csebagai doublesedikit lebih presisi (tetapi berhati-hatilah bahwa Anda masih akan mencapai batas presisi pada akhirnya).

nanofarad
sumber
3

Anda sebenarnya mencetak nilai dari dua jenis berbeda di sini.

Dalam kasus pertama Anda menetapkan nilai ke variabel tipe float. Presisi a floatkira-kira 6 atau 7 angka desimal, jadi kecuali jika nilainya dapat direpresentasikan dengan tepat Anda akan melihat nilai terdekat yang dapat diwakili oleh tipe itu.

Dalam kasus kedua Anda melewati konstanta 4.4e10yang bertipe double. Jenis ini memiliki sekitar 16 digit desimal presisi, dan nilainya berada dalam kisaran itu, sehingga nilai pastinya dicetak.

dbush
sumber
Mengapa secara spesifik mencetak 2048 di akhir?
user10056563
@ user10056563 Karena itu nomor terdekat dengan 4.4e10 yang dapat disimpan dalam float 32 bit.
dbush