Floating point logic is a sneaky problem in many programming languages, and Swift is no different. These innocent lines are completely incorrect:
let d1 = 0.1
let d2 = 0.2
let d3 = d1 + d2
if d3 == 0.3
{
//Do something
}
The contents of the if
statement will never execute. Floating point numbers on computers are notoriously imprecise beyond a certain number of digits (15 and 6 for Swift’s Double
and Float
types, respectively). While the details of this are fairly complex, it ultimately boils down to the limits of the bit space available to store the number – some numbers can’t be fully encoded in the memory representation so an approximation is used.
These custom operators provide a more useful implementation for comparing Double
values. The value chosen for the delta is useful in my case, but it needs to be tailored to your range of expected values. If you’re working with very large numbers, it’s likely it will need to be much larger.
infix operator ==~ { precedence 130 }
func ==~ (left: Double, right: Double) -> Bool
{
return fabs(left.distanceTo(right)) <= 1e-15
}
infix operator !=~ { precedence 130 }
func !=~ (left: Double, right: Double) -> Bool
{
return !(left ==~ right)
}
infix operator <=~ { precedence 130 }
func <=~ (left: Double, right: Double) -> Bool
{
return left ==~ right || left <~ right
}
infix operator >=~ { precedence 130 }
func >=~ (left: Double, right: Double) -> Bool
{
return left ==~ right || left >~ right
}
infix operator <~ { precedence 130 }
func <~ (left: Double, right: Double) -> Bool
{
return left.distanceTo(right) > 1e-15
}
infix operator >~ { precedence 130 }
func >~ (left: Double, right: Double) -> Bool
{
return left.distanceTo(right) < -1e-15
}