Come verificare l'uguaglianza di due numeri in virgola mobile (float)?
sobes.tech AI
Risposta dell'AI
Non è consigliabile confrontare direttamente con l'operatore == a causa delle peculiarità della rappresentazione e dell'arrotondamento. Invece, si dovrebbe verificare se il valore assoluto della differenza tra i numeri è entro una piccola soglia (epsilon).
bool are_equal(float a, float b, float epsilon = 0.00001f) {
return std::abs(a - b) < epsilon;
}
Un approccio più robusto considera l'errore relativo, specialmente quando si confrontano numeri molto grandi o molto piccoli:
#include <cmath>
#include <limits>
bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
// Confronta la differenza considerando la scala dei numeri
// È importante gestire separatamente i casi con zero e infinito
if (a == b) {
return true; // Gestisce i casi in cui a=b (inclusi infinito e NaN se sono uguali tra loro – cosa non vera per NaN, ma sì per infinito)
}
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; // Entrambi i numeri sono vicini a zero
} else {
return absolute_difference / max_abs < epsilon; // Confronto della differenza relativa
}
}
La scelta di epsilon dipende dalla precisione richiesta e dall'intervallo di valori da confrontare. std::numeric_limits<float>::epsilon() rappresenta il più piccolo numero tale che 1.0 + epsilon è diverso da 1.0.
È importante ricordare che il confronto con NaN (Not a Number) restituisce sempre false, incluso il confronto di NaN con se stesso (nan == nan è sempre false). Se si necessita di gestire NaN, questo deve essere fatto separatamente.