Regla 0x301Fh: No compares numeros de punto flotante con igualdad exacta
Memoria, punteros y tipos (0x30XX)
0x301Fh: No compares numeros de punto flotante con igualdad exacta¶
Enunciado normativo¶
NO DEBE compararse igualdad exacta (
==o!=) entre valores de punto flotante; usá una tolerancia.
Síntoma en el código del estudiante¶
Se compara un float o double contra un literal con ==, confiando en que el
valor calculado coincidirá exactamente:
if (f == 0.0f)
{
reportar_cero();
}Diagnóstico¶
Mecanismo del defecto¶
Los valores de punto flotante se representan con precisión finita IEEE-754
(ISO/IEC 9899:2011 §6.2.5). Operaciones como sumas, multiplicaciones o
divisiones introducen errores de redondeo que se acumulan. Un valor que
matemáticamente debería ser 0.0 puede valer 0.0000001 o -0.0, y entonces
la igualdad estricta falla.
Consecuencia observable¶
La rama de igualdad no se ejecuta aunque “debería”. El error es intermitente y
depende del compilador, las banderas de optimización y la plataforma
(x86 vs ARM, -O0 vs -O2). Es la causa clásica de comparaciones que
“funcionan en mi máquina”.
Fundamento en el estándar C11¶
ISO/IEC 9899:2011 §5.2.4.2.2 especifica las características de los tipos de punto flotante y §6.3.1.8 las conversiones usuales. La aritmética no es exacta; la igualdad estricta solo es fiable para valores representables con exactitud (enteros pequeños, potencias de dos). La cátedra exige comparar con tolerancia.
Corrección idiomática¶
❌ Código con el antipatrón¶
if (f == 0.0f)
{
reportar_cero();
}✅ Código refactorizado¶
#include <math.h>
if (fabs(f) < 1e-6)
{
reportar_cero();
}La comparación contra una tolerancia epsilon captura los valores
“matemáticamente cero” con error de redondeo. Para comparar dos valores a y
b, usar fabs(a - b) < epsilon.
Errores típicos al compilar o ejecutar¶
Con -Wfloat-equal (no incluida en -Wall):
warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
Sin advertencias, la rama no se ejecuta cuando f vale 0.0000001,
aunque el resultado matemático sea 0. El bug es intermitente.Checklist de verificación¶
¿Comparo
floatodoublecon==o!=?¿La igualdad depende de un cálculo con redondeo?
¿Reemplacé por una comparación con tolerancia
epsilon?¿La tolerancia elegida es adecuada a la escala de los valores?
Reglas relacionadas¶
0x301Bh: Prohibición de casts de tipo innecesarios o redundantes — evitar operaciones con flotantes donde no son necesarias.
0x1010h: Prohibición de comparaciones encadenadas no idiomáticas en C (a < b < c) — comparaciones explícitas y no encadenadas.
0x100Fh: Prohibición de cláusula else redundante tras sentencia de retorno anticipado — regla asociada a este antipatrón.