LoginSignup
34
18

More than 5 years have passed since last update.

Swift 4 で「プラマイ」範囲を作る

Last updated at Posted at 2017-09-07

どれだけの人が必要かわかりませんが、物理学とかやってると「AA ± aa」みたいな文言見たことあるんじゃ無いかと思います。つまり「正確には AA になるはずだが、実際の環境においてはそんな超絶に精密にぴったりそんな結果になるわけがないから、上下に aa の誤差がある」と言うようなことです。例えば 1kg の水が欲しいとき、測量機器によってそんなに精密に 1kg の水が出てくることはほとんどないから、例えばプラマイ 10g の誤差でも OK だよ、と言ったときに、1kg ± 10g で 990g ~ 1010g のニュアンスを表すことがよくあります。

Swift では範囲演算子 ... があるので、990 ... 1010 で書けば上記のその範囲を表すことができますが、ぱっと見「欲しいのは 1kg でプラマイの 10g は誤差だよ」と言うことはなかなか読み取りにくいと思います。そこで 1000 ± 10990 ... 1010 を表したいと思いました。というわけで早速演算子を定義します:

Operator.swift
infix operator ± : RangeFormationPrecedence

extension Numeric where Self: Comparable {

    public static func ± (lhs: Self, rhs: Self) -> ClosedRange<Self> {
        let added = lhs + rhs
        let subtracted = lhs - rhs
        let lowerBound = min(added, subtracted)
        let upperBound = max(added, subtracted)
        return lowerBound ... upperBound
    }

}

ここで Swift 4 の Numeric というプロトコルを使っています。このプロトコルは何のためにあるのかというと中に使っている +- の演算子が使えるということを保証しています。そしてなぜあえて (lhs - rhs) ... (lhs + rhs) を使わずに lowerBoundupperBound をそれぞれ minmax で定義しているのかというと、実際の利用時に rhs の値がマイナスになることも十分ありうると考えていますので、確実に lowerBoundupperBound を計算しました。

これで 1000 ± 10 を書けば 990 ... 1010 の範囲を返してくれます。便利ズイ₍₍(ง˘ω˘)ว⁾⁾ズイ

P.S.1
± どうやって入力するの」というツッコミをいただきましたが、まあ US 配列なら Opt + Shift + =± を入力できます。JIS は知らん。

P.S.2
ちなみに実用的な使い道として、iPhone の画面サイズが 16:9 かどうかを判定するときに、実際の計算ではぴったり 16.0 / 9.0 と結果が一致することがあまりないです(唯一一致するのは iPhone 6+ の 736.0 / 414.0 です)ので、逆に ((16.0 / 9.0) ± 0.01).contains(568.0 / 320.0) というふうに判定することができます。ちなみに自分はさらに …= という演算子も作っています。

34
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
18