Float Equality
ID |
swift.float_equality |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Swift |
Tags |
reliability, suspicious-code |
Description
Reports an == or != binary expression where at least one operand
is a bare floating-point literal. Most decimal fractions cannot be
represented exactly in binary, so a value that "should" equal the
literal after arithmetic rarely does.
if x == 0.0 { ... } // FLAW
if total != 1.0 { ... } // FLAW
if abs(x) < .ulpOfOne { ... } // OK — tolerance comparison
if n == 0 { ... } // OK — integer literal
Rationale
0.1 + 0.2 == 0.3 is false in every IEEE-754 implementation. The
problem is not Swift-specific, but the == operator on Double /
Float happily compiles and gives the impression of a meaningful
check. In practice the comparison is unreliable unless both sides
come from the same source (a stored constant, a Decimal, etc.).
Remediation
Compare using a tolerance, or use Decimal if exact arithmetic is
required:
let tolerance = 1.0e-9
if abs(x - target) < tolerance { ... }
// Or use Decimal for currency-like math:
let total: Decimal = 1.0
if amount == total { ... } // Decimal supports exact equality
The rule does not fire on integer literals (n == 0) and does not
fire on comparisons where the literal appears only inside a deeper
expression (e.g. inside a function call argument).