Contoh:
float timeRemaining = 0.58f;
Mengapa f
harus ada di akhir nomor ini?
c#
floating-point
Thomas
sumber
sumber
double
.double & int
.Jawaban:
Deklarasi float Anda berisi dua bagian:
timeRemaining
bertipefloat
.0.58
ke variabel ini.Masalahnya terjadi di bagian 2.
Sisi kanan dievaluasi dengan sendirinya. Menurut spesifikasi C #, angka yang mengandung titik desimal yang tidak memiliki sufiks diartikan sebagai a
double
.Jadi kita sekarang memiliki
double
nilai yang ingin kita tetapkan ke tipe variabelfloat
. Untuk melakukan ini, harus ada konversi implisit daridouble
menjadifloat
. Tidak ada konversi seperti itu, karena Anda mungkin (dan dalam hal ini memang) kehilangan informasi dalam konversi tersebut.Alasannya adalah nilai yang digunakan oleh compiler sebenarnya bukan 0,58, tetapi nilai floating-point yang paling dekat dengan 0,58, yaitu 0,57999999999999978655962351581366 ... untuk
double
dan tepat 0,579999946057796478271484375 untukfloat
.Sebenarnya,
f
tidak diperlukan. Anda dapat menghindari penggunaanf
sufiks dengan mentransmisikan nilai kefloat
:float timeRemaining = (float)0.58;
sumber
(float) 0.58
kerjanya? Tadi Anda mengatakan bahwa tidak ada konversi, karena informasi mungkin hilang, lalu kenapa pemeran bisa bekerja?2.4
diartikan sebagai dobel di tempat lain. 2. Konversi penyempitan implisit (seperti dari ganda menjadi mengambang) tidak diperbolehkan. Jika Anda ingin membuat pengecualian terhadap aturan ini, Anda harus memiliki alasan yang sangat bagus. Menyimpan 1 pukulan kunci sepertinya tidak cukup baik.Karena ada beberapa jenis numerik yang compiler dapat digunakan untuk mewakili nilai
0.58
:float
,double
dandecimal
. Kecuali Anda setuju dengan kompilator yang memilihkan satu untuk Anda, Anda harus mengerti.Dokumentasi untuk
double
menyatakan bahwa jika Anda tidak menentukan jenisnya sendiri, kompilator selalu memilihdouble
jenis literal numerik nyata apa pun:Menambahkan sufiks
f
membuat afloat
; sufiksd
menciptakan adouble
; akhiranm
menciptakan adecimal
. Semua ini juga bekerja dalam huruf besar.Namun, ini masih belum cukup untuk menjelaskan mengapa ini tidak dapat dikompilasi:
float timeRemaining = 0.58;
Setengah dari jawaban yang hilang adalah bahwa konversi dari the
double
0.58
kefloat
timeRemaining
berpotensi kehilangan informasi, sehingga compiler menolak untuk menerapkannya secara implisit. Jika Anda menambahkan cast eksplisit, konversi dilakukan; jika Anda menambahkanf
sufiks maka tidak diperlukan konversi. Dalam kedua kasus, kode kemudian akan dikompilasi.sumber
int
dan satu untukdouble
.double a = 0.69f;
?float
kedouble
.Masalahnya adalah bahwa .NET, untuk memungkinkan beberapa jenis operasi implisit dilakukan yang melibatkan
float
dandouble
, diperlukan baik secara eksplisit menentukan apa yang harus terjadi dalam semua skenario yang melibatkan operan campuran atau memungkinkan konversi implisit antara jenis yang akan dilakukan dalam satu arah saja; Microsoft memilih untuk mengikuti jejak Java dalam mengizinkan arah yang kadang-kadang lebih menyukai presisi, tetapi sering mengorbankan kebenaran dan umumnya menimbulkan kerumitan.Dalam hampir semua kasus, mengambil
double
nilai yang paling dekat dengan kuantitas numerik tertentu dan menugaskannya ke afloat
akan menghasilkanfloat
nilai yang paling dekat dengan kuantitas yang sama. Ada beberapa kasus sudut, seperti nilai 9.007.199.791.611.905;float
representasi terbaik akan menjadi 9.007.200.328.482.816 (yang dihapus oleh 536.870.911), tetapi memberikandouble
representasi terbaik (yaitu 9.007.199.791.611.904) untukfloat
menghasilkan 9.007.199.254.740.992 (yang turun sebesar 536.870.913). Namun secara umum, mengubahdouble
representasi terbaik dari beberapa kuantitas menjadifloat
akan menghasilkanfloat
representasi terbaik yang mungkin , atau salah satu dari dua representasi yang pada dasarnya sama baiknya.Perhatikan bahwa perilaku yang diinginkan ini berlaku bahkan pada kondisi ekstrem; misalnya,
float
representasi terbaik untuk kuantitas 10 ^ 308 cocok denganfloat
representasi yang dicapai dengan mengubahdouble
representasi terbaik dari kuantitas tersebut. Demikian juga,float
representasi terbaik dari 10 ^ 309 cocok denganfloat
representasi yang dicapai dengan mengubahdouble
representasi terbaik dari kuantitas tersebut.Sayangnya, konversi ke arah yang tidak memerlukan pemeran eksplisit jarang seakurat itu. Mengonversi
float
representasi terbaik dari suatu nilai menjadidouble
jarang akan menghasilkan sesuatu yang mendekatidouble
representasi terbaik dari nilai tersebut, dan dalam beberapa kasus hasilnya mungkin meleset oleh ratusan lipat (mis. Mengubahfloat
representasi terbaik dari 10 ^ 40 menjadidouble
akan menghasilkan nilai yang membandingkan lebih besar daridouble
representasi terbaik 10 ^ 300.Sayangnya, aturan konversi adalah apa adanya, jadi orang harus hidup dengan menggunakan typecast dan sufiks yang konyol saat mengonversi nilai ke arah "aman", dan berhati-hati dengan typecast implisit ke arah berbahaya yang sering kali akan menghasilkan hasil palsu.
sumber