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

  • Jose LviS el Bambino ( JLB )   LviSito

    Jose LviS el

    3 ŞUBAT 2008
  • chickenby

    chickenby

    2 HAZİRAN 2008
  • superemposed

    superemposed

    25 Aralık 2007