Cum să verifici egalitatea a două numere în virgulă mobilă (float)?
sobes.tech AI
Răspuns de la AI
Nu este recomandat să comparați direct cu operatorul == din cauza particularităților reprezentării și rotunjirii. În schimb, trebuie verificat dacă valoarea absolută a diferenței dintre numere se află în limitele mici (epsilon).
bool are_equal(float a, float b, float epsilon = 0.00001f) {
return std::abs(a - b) < epsilon;
}
O abordare mai robustă ia în considerare eroarea relativă, mai ales când comparăm numere foarte mari sau foarte mici:
#include <cmath>
#include <limits>
bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
// Compară diferența ținând cont de scala numerelor
// Este important să tratăm separat cazurile cu zero și infinit
if (a == b) {
return true; // Trata cazurile în care a=b (inclusiv infinit și NaN dacă sunt egale între ele – ceea ce nu este cazul pentru NaN, dar pentru infinit da)
}
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; // Ambele numere sunt apropiate de zero
} else {
return absolute_difference / max_abs < epsilon; // Compararea diferenței relative
}
}
Alegerea epsilon depinde de precizia necesară și de intervalul de valori comparate. std::numeric_limits<float>::epsilon() reprezintă cel mai mic număr astfel încât 1.0 + epsilon diferă de 1.0.
Este important să rețineți că comparația cu NaN (Not a Number) returnează întotdeauna false, inclusiv comparația nan == nan. Dacă este necesar să tratați NaN, acest lucru trebuie făcut separat.