Hoe controleer je de gelijkheid van twee drijvende-komma getallen (float)?
sobes.tech AI
Antwoord van AI
Het wordt niet aanbevolen om direct te vergelijken met de operator == vanwege de eigenschappen van de representatie en afronding. In plaats daarvan moet worden gecontroleerd of de absolute waarde van het verschil tussen de getallen binnen een kleine drempel (epsilon) ligt.
bool are_equal(float a, float b, float epsilon = 0.00001f) {
return std::abs(a - b) < epsilon;
}
Een meer robuuste aanpak houdt rekening met de relatieve fout, vooral bij het vergelijken van zeer grote of zeer kleine getallen:
#include <cmath>
#include <limits>
bool are_equal_robust(float a, float b, float epsilon = std::numeric_limits<float>::epsilon()) {
// Vergelijkt het verschil rekening houdend met de schaal van de getallen
// Het is belangrijk om gevallen met nul en oneindigheid apart te behandelen
if (a == b) {
return true; // Behandelt gevallen waar a=b (inclusief oneindigheid en NaN als ze gelijk zijn – wat niet het geval is voor NaN, maar wel voor oneindigheid)
}
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; // Beide getallen dicht bij nul
} else {
return absolute_difference / max_abs < epsilon; // Vergelijking van de relatieve afwijking
}
}
De keuze van epsilon hangt af van de vereiste precisie en het bereik van te vergelijken waarden. std::numeric_limits<float>::epsilon() vertegenwoordigt het kleinste getal zodat 1.0 + epsilon verschilt van 1.0.
Het is belangrijk om te onthouden dat vergelijking met NaN (Not a Number) altijd false oplevert, inclusief de vergelijking nan == nan. Als NaN-behandeling nodig is, moet dit apart worden gedaan.