はじめに
Swiftで同じであることを知りたいのであれば、==
を使えばわかります。
しかし、今回知りたいのは「ほぼ同じである」ことです。
「ある基準値より差が小さければ同じものであるとする」ということがしたいです。
どういうことかというと、
値A: 5.55550
値B: 5.55555
基準値を0.0001だとすると、上の例では値Aと値Bはほぼ同じであると言えます。
テストを書く際にこういうケースは割と発生すると思います。
実際、NimbleにもbeCloseTo
という機能があり、「ほぼ同じ」が再現できます。
どのように実装すれば最もスマートでしょうか?
Nimbleのコードを見てみる
値Aと値Bの差の絶対値を求めて、基準値より小さいかを見ているようです。
internal func isCloseTo(
_ actualValue: NMBDoubleConvertible?,
expectedValue: NMBDoubleConvertible,
delta: Double
) -> PredicateResult {
let errorMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))"
return PredicateResult(
bool: actualValue != nil &&
abs(actualValue!.doubleValue - expectedValue.doubleValue) < delta,
message: .expectedCustomValueTo(errorMessage, actual: "<\(stringify(actualValue))>")
)
}
Nimbleではほぼ同じの基準値をデフォルトで0.0001
に設定しているようです。
public func defaultDelta<F: FloatingPoint>() -> F { 1/10000 /* 0.0001 */ }
実装
イコールのように、ニアリーイコールを定義してみました。
基準値はNimbleを参考に0.0001
に設定しました。
import Foundation
infix operator ≒≒ : ComparisonPrecedence
func ≒≒(left: Double, right: Double) -> Bool {
return abs(left - right) < 0.0001
}
使い方
a
とb
の差が0.00005の時はtrue
を返します。
let a: Double = 5.55550
let b: Double = 5.55555
print(a ≒≒ b) // true
a
とb
の差が0.00015の時はfalse
を返します。
let a: Double = 5.55550
let b: Double = 5.55565
print(a ≒≒ b) // false
おわり
かなり勉強になりました
参考記事