Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork0
A correct way to determine if two floating-point numbers are approximately equal to one another in Swift
License
Flight-School/FloatingPointApproximation
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A correct way to determine if two floating-point numbersare approximately equal to one another.
This functionality is discussed in Chapter 3 ofFlight School Guide to Swift Numbers.
- Swift 4.0+
Add the FloatingPointApproximation package to your target dependencies inPackage.swift
:
import PackageDescriptionletpackage=Package( name:"YourProject", dependencies:[.package( url:"https://github.com/Flight-School/FloatingPointApproximation", from:"1.0.0"),])
Then run theswift build
command to build your project.
To useFloatingPointApproximation
in your Xcode project using Carthage,specify it inCartfile
:
github "Flight-School/FloatingPointApproximation" ~> 1.0.0
Then run thecarthage update
command to build the framework,and drag the built FloatingPointApproximation.framework into your Xcode project.
Floating-point arithmetic can produce unexpected results,such as0.1 + 0.2 != 0.3
.The reason for this is that many fractional numbers,including0.1
,0.2
, and0.3
,cannot be precisely expressed in a binary number representation.
A common mistake is to use an arbitrarily small constant(such as.ulpOfOne
)to determine whether two floating-point numbers are approximately equal.For example:
letactual=0.1+0.2letexpected=0.3abs(expected- actual)<.ulpOfOne // true
However, this doesn't work for large scale numbers:
letactual=1e25+2e25letexpected=3e25abs(expected- actual)<.ulpOfOne // false
A better approach for determining approximate equalitywould be to count how many representable values, or ULPs,exist between two floating-point numbers.
The==~
operator (and its complement,!=~
)defined by this packagereturns a Boolean value indicating whethertwo floating-point numbers are approximately equal.
import FloatingPointApproximation0.1+0.2==0.3 // false0.1+0.2==~0.3 // true
Floating-point numbers are defined to be approximately equalif they are within oneunit of least precision, orULP,of one another.
Because of how Swift implements floating-point numbers,the implementation of the==~
operator is quite simple:
func==~<T>(lhs:T, rhs:T)->Boolwhere T:FloatingPoint{return lhs== rhs || lhs.nextDown== rhs || lhs.nextUp== rhs}
A more complete approach combines both absolute and relative comparisons.TheisApproximatelyEqual(to:within:maximumULPs:)
methoddetermines whether a floating-point numberis approximately equal to another valueby first checking to see if it is within a given absolute margin, if provided,and then checking to see if it falls within a given number of ULPs:
import FloatingPointApproximation(0.1+0.2).isApproximatelyEqual(to:0.3, within:1e-12, maximumULPs:2)
Ultimately, it's your responsibility to determine how to comparetwo floating-point numbers for approximate equalitybased on the requirements of your domain.
MIT
Mattt (@mattt)
About
A correct way to determine if two floating-point numbers are approximately equal to one another in Swift
Topics
Resources
License
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.