Sobes.tech
Junior

Kā pārbaudīt divu peldošo punktu skaitļu (float) vienādību?

sobes.tech AI

Atbilde no AI

Tiešā salīdzināšana ar operatoru == nav ieteicama, ņemot vērā pārstāvības un noapaļošanas īpatnības. Tā vietā jāparbauda, vai abu skaitļu absolūtā atšķirība ir mazāka par nelielu slieksni (epsilon).

bool are_equal(float a, float b, float epsilon = 0.00001f) {
    return std::abs(a - b) < epsilon;
}

Vairāk izturīgs pieejas ņem vērā relatīvo kļūdu, īpaši, salīdzinot ļoti lielus vai ļoti mazus skaitļus:

#include <cmath>
#include <limits>

bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
    // Salīdzina atšķirību, ņemot vērā skaitļu mērogu
    // Ir svarīgi atsevišķi apstrādāt nulles un bezgalības gadījumus
    if (a == b) {
        return true; // Apstrādā gadījumus, kad a=b (ieskaitot bezgalību un NaN, ja tie ir vienādi – kas nav NaN gadījumā, bet ir bezgalība)
    }

    float absolute_difference = std::abs(a - b);
    float max_abs = std::max(std::abs(a), std::abs(b));

    if (max_abs < epsilon) {
        return absolute_difference < epsilon; // Abi skaitļi ir tuvu nullei
    } else {
        return absolute_difference / max_abs < epsilon; // Relatīvās atšķirības salīdzinājums
    }
}

epsilon izvēle ir atkarīga no nepieciešamās precizitātes un salīdzināmo vērtību diapazona. std::numeric_limits<float>::epsilon() apzīmē mazāko skaitli, kuram ir īpašība, ka 1.0 + epsilon atšķiras no 1.0.

Svarīgi atcerēties, ka NaN (Not a Number) salīdzinājums vienmēr atgriež false, ieskaitot nan == nan. Ja nepieciešams, NaN jāapstrādā atsevišķi.