Sobes.tech
Junior

Hogyan ellenőrizzük két lebegőpontos szám (float) egyenlőségét?

sobes.tech MI

Válasz az MI-től

Nem ajánlott közvetlenül az == operátorral összehasonlítani a reprezentáció és a kerekítés sajátosságai miatt. Ehelyett meg kell vizsgálni, hogy a számok közötti különbség abszolút értéke egy kis küszöbön (epsilon) belül van-e.

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

Egy robusztusabb megközelítés figyelembe veszi a relatív hibát, különösen nagy vagy kicsi számok összehasonlításakor:

#include <cmath>
#include <limits>

bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
    // A különbséget a számok skáláját figyelembe véve hasonlítjuk össze
    // Fontos külön kezelni a nullát és a végtelent
    if (a == b) {
        return true; // Kezeli az a=b eseteket (beleértve a végtelent és NaN-t, ha egymáshoz hasonlóak – ami nem igaz NaN esetén, de végtelen esetén igen)
    }

    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; // Mindkét szám közel van a nullához
    } else {
        return absolute_difference / max_abs < epsilon; // Relatív különbség összehasonlítása
    }
}

Az epsilon kiválasztása a szükséges pontosságtól és az összehasonlítandó értékek tartományától függ. A std::numeric_limits<float>::epsilon() a legkisebb számot jelenti, amelynél az 1.0 + epsilon különbözik az 1.0-tól.

Fontos megjegyezni, hogy a NaN (Not a Number) értékekkel való összehasonlítás mindig hamisat ad, beleértve a nan == nan kifejezést is. Ha NaN kezelése szükséges, azt külön kell kezelni.