Sobes.tech
Junior

Comment vérifier l'égalité de deux nombres à virgule flottante (float) ?

sobes.tech IA

Réponse de l'IA

Il n'est pas recommandé de comparer directement avec l'opérateur == en raison des particularités de la représentation et de l'arrondi. À la place, il faut vérifier si la valeur absolue de la différence entre les nombres est dans une petite marge (epsilon).

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

Une approche plus robuste prend en compte l'erreur relative, surtout lors de la comparaison de nombres très grands ou très petits :

#include <cmath>
#include <limits>

bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
    // Compare la différence en tenant compte de l'échelle des nombres
    // Il est important de traiter séparément les cas avec zéro et infini
    if (a == b) {
        return true; // Gère les cas où a=b (y compris infini et NaN si ils sont égaux entre eux – ce qui n'est pas le cas pour NaN, mais pour infini oui)
    }

    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; // Les deux nombres sont proches de zéro
    } else {
        return absolute_difference / max_abs < epsilon; // Comparaison de la différence relative
    }
}

Le choix de epsilon dépend de la précision requise et de la plage de valeurs à comparer. std::numeric_limits<float>::epsilon() représente le plus petit nombre tel que 1.0 + epsilon est différent de 1.0.

Il est important de se rappeler que la comparaison avec NaN (Not a Number) retourne toujours false, y compris la comparaison de NaN avec lui-même (nan == nan est toujours false). Si la gestion de NaN est nécessaire, cela doit être fait séparément.