Maaf, ini mungkin pertanyaan bodoh yang mudah, tapi saya perlu tahu untuk memastikannya.
Saya memiliki if
ekspresi ini ,
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
Apakah ungkapan itu sama dengan
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? Karena saya mungkin memiliki masalah, memasukkan if
dengan misalnya nilai 0,9.
// Comparison of floating point numbers with equality // operator.
Apakah Anda benar-benar perlu menjelaskannya? :)Jawaban:
Nah, seberapa dekat Anda membutuhkan nilainya dengan 0? Jika Anda melalui banyak operasi floating point yang dalam "presisi tak terbatas" mungkin menghasilkan 0, Anda bisa mendapatkan hasil "sangat dekat" dengan 0.
Biasanya dalam situasi ini Anda ingin memberikan semacam epsilon, dan memeriksa apakah hasilnya tepat di dalam epsilon itu:
if (Math.Abs(something) < 0.001)
Epsilon yang harus Anda gunakan adalah khusus aplikasi - itu tergantung pada apa yang Anda lakukan.
Tentu saja, jika hasilnya benar - benar nol, maka pemeriksaan persamaan sederhana sudah cukup.
sumber
== 0
. Anda punya literal di sana - itu cukup konstan :)Jika
something
telah ditetapkan dari hasil operasi selain darisomething = 0
maka Anda lebih baik menggunakan:if(Math.Abs(something) < Double.Epsilon) { //do something }
Edit : Kode ini salah. Epsilon adalah angka terkecil, tetapi tidak cukup nol. Ketika Anda ingin membandingkan suatu angka dengan angka lain, Anda perlu memikirkan toleransi yang dapat diterima. Katakanlah apa pun di luar 0,00001 yang tidak Anda pedulikan. Itu nomor yang Anda gunakan. Nilainya bergantung pada domain. Namun, sebagian besar pasti tidak pernah Double.Epsilon.
sumber
Math.Abs(0.1f - 0.1d) < double.Epsilon
adalahfalse
double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
Anda
something
adalah adouble
, dan Anda telah mengidentifikasinya dengan benar di barisif (something == 0)
kita memiliki a
double
di sisi kiri (lhs) danint
di sisi kanan (rhs).Tapi sekarang sepertinya Anda berpikir lhs akan diubah menjadi
int
, dan kemudian==
tanda akan membandingkan dua bilangan bulat. Itu bukan apa yang terjadi. Konversi daridouble
keint
adalah eksplisit dan tidak dapat terjadi "otomatis".Sebaliknya, yang terjadi justru sebaliknya. Rhs diubah menjadi
double
, dan kemudian==
tanda itu menjadi uji kesetaraan antara dua ganda. Konversi ini implisit (otomatis).Menulis dianggap lebih baik (oleh beberapa orang)
if (something == 0.0)
atau
if (something == 0d)
karena Anda akan segera membandingkan dua ganda. Namun, itu hanya masalah gaya dan keterbacaan karena kompilator akan melakukan hal yang sama dalam hal apa pun.
Juga relevan, dalam beberapa kasus, untuk memperkenalkan "toleransi" seperti dalam jawaban Jon Skeet, tetapi toleransi itu juga akan menjadi
double
. Ini bisa saja menjadi1.0
jika Anda ingin, tetapi tidak harus [paling ketat positif] integer.sumber
Jika Anda hanya ingin menekan peringatan tersebut, lakukan ini:
if (something.Equals(0.0))
Tentu saja, ini hanya solusi yang valid jika Anda tahu bahwa drift bukanlah masalah. Saya sering melakukan ini untuk memeriksa apakah saya akan membagi dengan nol.
sumber
Sejujurnya, saya tidak berpikir itu sama. Pertimbangkan contoh Anda sendiri: sesuatu = 0,9, atau 0,0004. Dalam kasus pertama akan menjadi SALAH, dalam kasus kedua akan BENAR. Berurusan dengan jenis ini saya biasanya menentukan untuk saya persentase presisi dan membandingkan dalam presisi itu. Tergantung kebutuhan Anda. sesuatu seperti...
if(((int)(something*100)) == 0) { //do something }
Semoga ini membantu.
sumber
Berikut adalah contoh masalah (disiapkan di LinQPad - jika Anda tidak memilikinya, gunakan saja
Console.Writeline
alih-alihDump
metode):void Main() { double x = 0.000001 / 0.1; double y = 0.001 * 0.01; double res = (x-y); res.Dump(); (res == 0).Dump(); }
Baik x dan y secara teoritis sama dan sama dengan: 0,00001 tetapi karena kurangnya "presisi tak terbatas", nilai-nilai tersebut sedikit berbeda. Sayangnya cukup sedikit untuk kembali
false
saat membandingkan ke 0 dengan cara biasa.sumber