2011-12-09

Porównywanie liczb z marginesem błędu

W obliczeniach na liczbach zmiennoprzecinkowych w wyniku błędów zaokrąglania w wielu miejscach nie możemy porównywać liczb w sposób absolutny. Np. przyrównywać ich do np. 0 podczas wyliczania wyznaczników wielomianów. W takich sytuacjach pozostaje nam porównanie liczb z pewnym marginesem. Liczby możemy porównywać względnie i bezwzględnie. Np. porównywanie dwóch liczb z dokładnością bezwzględną 1e-12, kiedy różnica pomiędzy nimi może się wahać od 1 do miliona nie ma sensu. Porównywanie liczb bezwzględne ma tylko sens jeśli porównywane liczby mieszczą się w pewnym zakresie - są w jakiś sposób normowane. Oczywiście takie porównywanie jest szybsze niż porównywanie względne.

Oto aktualnie przeze mnie wykorzystywany kod na porównywanie liczb w sposób względny i bezwzględny:
public static bool AlmostEquals(
    this double a_d1, double a_d2, double a_precision)
{
    return Math.Abs(a_d1 - a_d2) < a_precision;
}

public static bool AlmostRelativeEquals(
    this double a_d1, double a_d2, double a_precision)
{
    double mid = Math.Max(Math.Abs(a_d1), Math.Abs(a_d2));
            
 if (Double.IsInfinity(mid))
        return false;
    
    if (mid > a_precision)
        return Math.Abs(a_d1 - a_d2) <= a_precision * mid;
    else
        return a_d1 < a_precision;
}

Brak komentarzy:

Prześlij komentarz