SORU
6 ŞUBAT 2011, Pazar


Nasıl kayan nokta karşılaştırma yapayım mı?

Şu anda çizgisinde bir şey var, bazı kod yazıyorum:

double a = SomeCalculation1();
double b = SomeCalculation2();

if (a < b)
    DoSomething2();
else if (a > b)
    DoSomething3();

Ve başka yerlerde eşitlik yapmaya ihtiyacım olabilir:

double a = SomeCalculation3();
double b = SomeCalculation4();

if (a == 0.0)
   DoSomethingUseful(1 / a);
if (b == 0.0)
   return 0; // or something else here

Kısacası, kayan nokta matematik bir sürü olay oluyor ve koşulları için çeşitli karşılaştırmalar yapmak istiyorum. Böyle bir şey bu bağlamda anlamsızdır çünkü tamsayı matematik dönüştürmek istemiyorum.

Böyle şeyler olabilir bu yana kayan nokta karşılaştırma güvenilmez olabilir okuyun önce.

double a = 1.0 / 3.0;
double b = a   a   a;
if (a != b)
    Console.WriteLine("Oh no!");

Kısacası, bilmek istiyorum: Ne kadar güvenilir nokta sayıları (küçüktür, büyüktür, eşitlik) kayan karşılaştırabilir miyim?

Kullanıyorum sayı aralığı 10E6, bu yüzden 10E-14 küçük sayı ile büyük olarak işe ihtiyacım var kabaca.

Şu an kullandığım ne olursa olsun başarmak ben nasıl ilgileniyorum çünkü dil agnostik olarak etiketlenmiş ettim.

CEVAP
6 ŞUBAT 2011, Pazar


Büyük/küçük karşılaştırarak doğru kaydır/çift duyarlıklı sınırı kenarında çalışmadığınız sürece gerçekten bir sorun değildir.

Bir "bulanık eşit" karşılaştırma, bu (Java kod, kolay olmalı uyum) ne ben ile geldi The Floating-Point Guide sonra çok güzel ve dikkate alınması çok eleştiri:

public static boolean nearlyEqual(float a, float b, float epsilon) {
    final float absA = Math.abs(a);
    final float absB = Math.abs(b);
    final float diff = Math.abs(a - b);

    if (a == b) { // shortcut, handles infinities
        return true;
    } else if (a == 0 || b == 0 || diff < Float.MIN_NORMAL) {
        // a or b is zero or both are extremely close to it
        // relative error is less meaningful here
        return diff < (epsilon * Float.MIN_NORMAL);
    } else { // use relative error
        return diff / (absA   absB) < epsilon;
    }
}

Bir test paketi ile birlikte geliyor. Hemen hemen bir değeri 0, sıfır ya da sonsuz çok küçük iki değer tersi olması gibi bazı kenar durumlarda başarısız garanti olduğu için mi, değil herhangi bir çözüm göndermelisiniz.

Alternatif (yukarıdaki bağlantıya daha fazla ayrıntı için bakınız) yüzer' bit ve sabit tamsayı bir mesafe içinde her şey tamsayı kabul desenler. dönüştürülmesidir

Herhangi bir durumda, muhtemelen tüm uygulamalar için mükemmel bir çözüm yok. İdeal olarak, geliştirme/test suite gerçek kullanım davalarını kapsayan kendi adapte edersin.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Android Central

    Android Cent

    13 Kasım 2008
  • Microsoft Help & Training Videos

    Microsoft He

    31 Mart 2009
  • pucksz

    pucksz

    24 Mart 2006