Bu kıyaslama işlemi fazlasıyla sıkıntılı bir iş. Pratikte çoğunlukla işe yarayacak ipuçlarını paylaşayım dedim. Kolaylık olsun diye yazının geri kalanında kayan noktalı sayılar için double kelimesini kullanacağım, söylediğim şeyler float gibi herhangi bir kayan noktalı sayı gösterimi için geçerlidir.
Altın kural: Asla, ama asla, iki double'ı == ya da != gibi karşılaştırma operatörleriyle doğrudan kıyaslamayın. Çoğunlukla eşit olmayacaklardır.
- Yaklaşık eşitliği sınayan fonksiyonunuz olsun, heryerde aynısını kullanın.
approxEqual(double a, double b, double eps=machine_epsilon) return abs(a-b) <= max(a,b)*eps;
max()yerine
min()de kullanılabilir. Bunu yapınca tabi ki fonksiyonun davranışı değişecek, mühim olan hassasiyetinizi kıyaslanacak sayılara göre ölçeklemek.
- Bir double'ı sıfırla kıyaslayacaksanız işler karışıyor. Genelde kıyaslayacağınız sayı kabul edilebilir seviyede küçük, fakat sıfırdan hatrı sayılır derecede (hatta sonsuz kat) büyük olacaktır. Yukarıdaki
approxEqual()bu durumda işe yaramayacaktır. Sıfırla kıyaslama durumunu ayrıca değerlendirin.
approxZero(double d, double eps=machine_epsilon) return abs(d)<=eps;
- İki sayının farkını sıfırla kıyaslamak yerine, iki sayıyı birbiriyle kıyaslayın. Bir önceki maddede açıkladığım gibi sıfırla kıyaslama daha problemli bir iş.
- Bu iki yaklaşım da tam olarak doğru yaklaşımlar değil aslında, ama çoğunlukla işinizi görecektir. Hassasiyet hatalarıyla başetmenin kesin yolu hatanın analizini yapıp yukarıdaki fonksiyonlarda
epsdeğişkeninin varsayılan değerini kullanmak yerine hesapladığınız teorik hataya göre bir
epsseçmek. Bunu yapmak genelde çok zor. İkinci yol ise deneme yanılma; işinize yarayacak epsilon değerini el yordamıyla bulacaksınız.
- Kayan noktalı sayılarla işlem yapmaca göründüğünden ve sandığınızdan çok daha zor ve karmaşık bir iş. Örneğin kıyasladığınız iki sayıdan birinin sıfır olma ihtimali varsa allah yardımcınız olsun.
machine_epsilondiye kodladığım değişkeni genelde kullandığınız programlama dili size bir sabit olarak verir, dökümantasyonunuza bakın.
Dediğim gibi kayan noktalı sayılar çok derin bir konu ve ancak şöyle bir üzerinden yalayıp geçtim. Yazdığım kadarı günlük kullanım için yeterli olur herhalde.