Por que esse lint aparece¶
Números de ponto flutuante (float, f32, f64) são armazenados em binário IEEE-754. A maioria das frações decimais — inclusive valores familiares como 0.1 e 0.2 — não tem representação binária exata, então o valor que a CPU realmente armazena é próximo do que você escreveu, não igual.
fn main() {
let a = 0.1 + 0.2
let b = 0.3
print(a == b) // false — `a` é 0.30000000000000004
}Por isso, comparar dois floats com == ou != quase sempre é a pergunta errada. O lint dispara sempre que pelo menos um lado de uma == / != é um literal de ponto flutuante.
O que usar no lugar¶
Zolo oferece quatro alternativas idiomáticas. Escolha a que casa com a pergunta que você realmente quer fazer.
~= e !~= — igualdade aproximada (tolerância adaptativa)¶
O operador ~= combina tolerância absoluta e relativa, lidando bem tanto com valores muito pequenos quanto muito grandes sem precisar de ajuste manual:
let a = 0.1 + 0.2
let b = 0.3
print(a ~= b) // true
print(a !~= b) // falseUse este para o caso comum (90% das vezes) onde a pergunta é "esses números são basicamente iguais?".
math.approx_eq_abs(a, b, tol) — tolerância absoluta explícita¶
Quando você tem um orçamento de precisão conhecido (ex.: "dentro de 1 mm"):
math.approx_eq_abs(medido, esperado, 0.001)math.approx_eq_rel(a, b, rtol) — tolerância relativa explícita¶
Quando a precisão deve escalar com a magnitude (ex.: "dentro de 0,1% do valor esperado"):
math.approx_eq_rel(medido, esperado, 0.001)math.is_nan(x) — checagem de NaN¶
x == x é false para NaN — isso é IEEE-754, não bug. Use o helper específico:
if math.is_nan(valor) {
return Err("valor é NaN")
}Quando você realmente precisa de igualdade exata¶
Para valores que precisam ser comparados exatamente — dinheiro, identificadores, qualquer coisa que sobrevive a serialização — não use float de jeito nenhum. Use o tipo decimal (ou bigdecimal):
let preco: decimal = 19.99d
let total: decimal = preco * 3
print(total == 59.97d) // true — exatoVeja /docs/float-precision para o guia completo sobre tipos decimais e ferramentas de comparação de floats.
Suprimindo o lint¶
Se você auditou uma comparação específica e tem certeza de que o == está correto (ex.: comparando contra uma sentinela como 0.0 que o seu próprio código produziu), desabilite só naquela expressão:
@diagnostic(off, "float-equality")
fn is_zero_sentinel(x: float) -> bool {
return x == 0.0
}Ou, em escopo de arquivo, pelo lint config. Prefira a forma estreita — quanto mais amplo o silenciamento, maior a chance de bugs reais passarem.