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.