Por qué se dispara este lint¶
Los números de coma flotante (float, f32, f64) se almacenan en binario IEEE-754. La mayoría de las fracciones decimales — incluso valores familiares como 0.1 y 0.2 — no tienen representación binaria exacta, así que el valor que realmente almacena la CPU es cercano a lo que escribiste, no igual.
fn main() {
let a = 0.1 + 0.2
let b = 0.3
print(a == b) // false — `a` es 0.30000000000000004
}Por eso, comparar dos floats con == o != casi siempre es la pregunta equivocada. El lint se dispara siempre que al menos un lado de un == / != es un literal de coma flotante.
Qué usar en su lugar¶
Zolo ofrece cuatro alternativas idiomáticas. Elige la que coincida con la pregunta que realmente quieres hacer.
~= y !~= — igualdad aproximada (tolerancia adaptativa)¶
El operador ~= combina tolerancia absoluta y relativa, gestionando bien tanto valores muy pequeños como muy grandes sin necesidad de ajuste manual:
let a = 0.1 + 0.2
let b = 0.3
print(a ~= b) // true
print(a !~= b) // falseUsa esta para el caso común (90% de las veces) donde la pregunta es "¿son estos números básicamente iguales?".
math.approx_eq_abs(a, b, tol) — tolerancia absoluta explícita¶
Cuando tienes un presupuesto de precisión conocido (ej.: "dentro de 1 mm"):
math.approx_eq_abs(medido, esperado, 0.001)math.approx_eq_rel(a, b, rtol) — tolerancia relativa explícita¶
Cuando la precisión debe escalar con la magnitud (ej.: "dentro del 0,1% del valor esperado"):
math.approx_eq_rel(medido, esperado, 0.001)math.is_nan(x) — comprobación de NaN¶
x == x es false para NaN — eso es IEEE-754, no un bug. Usa el helper dedicado:
if math.is_nan(valor) {
return Err("valor es NaN")
}Cuando realmente quieres igualdad exacta¶
Para valores que deben compararse exactamente — dinero, identificadores, cualquier cosa que sobrevive a serialización — no uses float en absoluto. Usa el tipo decimal (o bigdecimal):
let precio: decimal = 19.99d
let total: decimal = precio * 3
print(total == 59.97d) // true — exactoConsulta /docs/float-precision para la guía completa sobre tipos decimales y herramientas de comparación de floats.
Suprimiendo el lint¶
Si auditaste una comparación específica y sabes que == es correcto (ej.: comparando contra un centinela como 0.0 producido por tu propio código), desactívalo solo para esa expresión:
@diagnostic(off, "float-equality")
fn is_zero_sentinel(x: float) -> bool {
return x == 0.0
}O, a nivel de archivo, vía la configuración del linter. Prefiere la forma estrecha — cuanto más amplio el silenciamiento, mayor la probabilidad de que pasen bugs reales.