Help us understand the problem. What is going on with this article?

Swift演算子まとめ

Swiftの演算子、まとめました。

【2018/09/05追記】
内容はSwift2のものであり、(筆者がiOS開発を離れているため)更新の予定もありません😉
編集リクエストは大歓迎です。@BlueRayi さんありがとうございました。

演算子一覧

Prefix演算子

演算子 作用
++ 1加算※
-- 1減算※
! 論理NOT
~ ビットNOT
+ (単項) +符号
- (単項) -符号

Postfix演算子

演算子 説明
++ 1加算※
-- 1減算※

Infix演算子

演算子 説明 結合律 優先順位
<< 左ビットシフト 無結合 160
>> 右ビットシフト 無結合 160
* 乗算 左結合 160
/ 除算 左結合 160
% 剰余 左結合 160
&* オーバーフロー乗算 左結合 160
& ビットAND 左結合 160
+ 加算 左結合 140
- 減算 左結合 140
&+ オーバーフロー加算 左結合 140
&- オーバーフロー減算 左結合 140
| ビットOR 左結合 140
^ ビットXOR 左結合 140
..< 半開区間 無結合 135
... 閉区間 無結合 135
is 型チェック 左結合 132
as as? as! 型キャスト 左結合 132
?? Nil Coalescing 右結合 131
< 未満 無結合 130
<= 以下 無結合 130
> より上 無結合 130
>= 以上 無結合 130
== イコール 無結合 130
!= ノットイコール 無結合 130
=== 同じオブジェクト 無結合 130
!== 違うオブジェクト 無結合 130
~= パターンマッチ 無結合 130
&& 論理AND 左結合 120
|| 論理OR 左結合 110
?: 三項条件 右結合 100
= 代入 右結合 90
*= 乗算と代入 右結合 90
/= 徐算と代入 右結合 90
%= 剰余と代入 右結合 90
+= 加算と代入 右結合 90
-= 減算と代入 右結合 90
<<= 左ビットシフトと代入 右結合 90
>>= 右ビットシフトと代入 右結合 90
&= ビットANDと代入 右結合 90
|= ビットORと代入 右結合 90
^= ビットNOTと代入 右結合 90
&&= 論理ANDと代入 右結合 90
||= 論理ORと代入 右結合 90

※…++演算子、--演算子はSwift3.0で削除された。

用語

単項演算子(Unary)
被演算子(Operand)が1つの演算子。
前置のもの(prefix)と後置のもの(postfix)がある。

二項演算子(Binary)
被演算子が2つの演算子。
被演算子の間に置かれる(infix)。

三項演算子(Ternary)
被演算子が3つの演算子。
?:の一つだけ(infix)。

優先順位
数値が大きいものほど先に演算される。
単項演算子は二項演算子よりも優先順位が高い。

結合律
優先順位が同じ演算子が並んだ場合は、左結合のものは左から、右結合のものは右から演算される。
(同じ優先順位で、左結合のものと右結合のものは混在しない。)
無結合の演算子が並んだ場合はエラーとなる。

let result = 2 + 3 + 4  // 左から

var str1: String?
var str2: String?
let string = str1 ?? str2 ?? "string" // 右から

let int1 = 1
let int2 = 2
let int3 = 3
int1 == int2 == int3 // エラー

各演算子

代入演算子(Assignment Operator)

=

値の代入。
タプルの場合はそれぞれに代入。
Objective-Cと異なり、値を返さない。

let (x, y) = (1, 2)
// x = 1, y = 2

if x = y { // 判定する値が返らない
    // エラー
}

算術演算子

+, -, *, /

Objective-Cと異なり、オーバーフローを許容しない。

var i: Int8 = 127 // Int8の最大数
i++  // エラー

%

a % b は

a = (b * 整数) + 余り

と解釈される。

-9 % 4 // (4 * -2) - 1 
// -1
-9 % -4 // (-4 * 2) - 1 
// -1

また、Float型にも適用可能。

8 % 2.5 // 0.5

++, --

それぞれ、1の加算、1の減算となる。
prefixは演算の後に値を返し、postfixは値を返した後に演算を行う。
Swift3.0からは削除されたため、+=演算子、-=演算子などを使って代用する(ただし、これらの演算子は値を返さない)。

var a = 0, b = 0
let c = ++a // 1
let d = b++ // 0

+, - (単項)

符号を表す。

オーバーフロー演算子

&+, &-, &*

オーバーフローを許容する演算子。

var i: Int8 = 127 // Int8の最大数
i &+ 1 // -128: Int8の最小数

比較演算子

==, !=, <, >, <=, >=

それぞれ比較の結果のBool値を返す。

===, !==

被演算子が同じオブジェクトを参照しているかどうかを判定する。
(被演算子はクラスのオブジェクト)

三項条件演算子

?:

Swift唯一の三項演算子。

let isSelected = true

if isSelected {
    print("true")
} else {
    print("false")
}
// ↓同じ
isSelected ? print("true") : print("false")

Nil Coalescing 演算子

??

a ?? b (aはオプショナル型)
aがnilのときbを返す演算子。

let alpha: Int? = nil
let beta: Int = 10

alpha != nil ? alpha! : beta
// ↓同じ
alpha ?? beta

パターンマッチ

~=

パターンマッチの結果をBool値で返す。
区間(後述)のマッチによく使われる。

0...100 ~= 15 // true

switch文のcase分岐の際、内部で使われている演算子。

区間演算子

両側が整数 → Range型:for-inに使える。
片側or両側が浮動小数点数 → ClosedInterval型(閉区間)、HalfOpenInterval型(半開区間):for-inに使えない。

...

閉区間:右側の数が含まれる区間。

0...100 ~= 100 // true

..<

半開区間:右側の数を含まない区間。

0..<100 ~= 100 // false

論理演算子(Logical Operators)

Swiftで論理演算子の被演算子となるはBool型のみ。

!

論理NOT

var isSelected: Bool = true
!isSelected // false

&&

論理AND

0 1
0 0 0
1 0 1

(便宜的に、0: false, 1: true)

||

論理OR

0 1
0 0 1
1 1 1

(便宜的に、0: false, 1: true)

ビット演算子

整数値を2進数で表したとき、それぞれの桁同士を論理演算した値を返す。

~

ビットNOT
それぞれの桁同士にNOT演算。

let bit: UInt8 = 0b00001111 // = 15
// ↓
~bit // 0b11110000 = 240

(0bは2進数を表すリテラル。)

&

ビットAND
それぞれの桁同士にAND演算。

let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 & bit2 // 0b11110000 = 240

|

ビットOR
それぞれの桁同士にOR演算。

let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 | bit2 // 0b11111100 = 252

^

ビットXOR
それぞれの桁同士にXOR演算。

XOR演算は以下の表の通り。

0 1
0 0 1
1 1 0

(0: false, 1: true)

let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 ^ bit2 // 0b00001100 = 12

<<, >>

ビットシフト演算子
それぞれの桁を右または左に指定した値シフトする。
シフトにより空いた桁を埋める値は、整数型が符号ありか符号なしかで異なる。

  • 符号なし整数(Unsigned Int)

シフトにより空いた桁を0で埋める

let unsignedInt: UInt8 = 0b11111111 // 255
// ↓
unsignedInt << 4 // 0b11110000 = 240
unsignedInt >> 4 // 0b00001111 = 15
  • 符号あり整数(Signed Int)

最上位の桁は符号ビット(the sign bit)といい、0で正、1で負を表す。
符号あり整数の場合、シフトにより空いた桁は符号ビットの値で埋められる。

let signedPlusInt: Int8 = 127 // 0b0_1111111
signedPlusInt >> 4 // 0b0_0000111 = 7
signedPlusInt << 4 // 0b1_1110000 = -16
// 空いた桁を0で埋めている

let signedMinusInt: Int8 = -127 // 0b1_0000000
signedMinusInt >> 4 // 0b1_1111000 = -8
signedMinusInt << 4 // 0b0_0001111 = 16
// 空いた桁を1で埋めている

参考:マイナス値の2進数での表し方

複合代入演算子

各々の演算後に、結果を代入する演算子。

+=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=, &&=, ||=

var int: Int = 3

int += 5
// ↓同じ
int = int + 5


var bit: UInt8 = 0b11110000 // 240

bit <<= 4 // 0b00000000 = 0
// ↓同じ
bit = bit << 4

型チェック、型キャスト

is

型チェック。
左項のオブジェクトが右項の型に一致すればtrue、異なればfalseを返す。

let str: Any = "string"
str is String // true

as, as? as!

ダウンキャストを行う。

let str: String = "string"
str as NSString

as!はダウンキャストに失敗した場合、クラッシュする。
as?はダウンキャストに失敗した場合、nilが入る。

let str: Any = "string"
str as! Int // 実行時エラー
str as? Int // nil

演算子オーバーロード

既存の演算子の書き換え・定義されてない型への定義。
オーバーロードとカスタム演算子(後述)の導入が可能なのは単項演算子と二項演算子のみ。
書き換えは用法と用量を守りましょう。

// * を + に書き換え
func * (left: Int, right: Int) -> Int {
    return left + right
}

2 * 3 // 5

// 左側;String、右側:Intに + を定義
func + (left: String, right: Int) -> String {
    return left + String(right)
}

"Number: " + 3 // "Number: 3"

カスタム演算子

新たに演算子を定義。

// 累乗を計算する演算子を定義
infix operator ** { associativity left precedence 161 }
func ** (left: Int, right: UInt) -> Int {
    var powered = 1
    for _ in 0..<right {
        powered *= left
    }

    return powered
}

2 + 3 ** 2 // 11

参考文献

The Swift Programming Language
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_StandardLibrary_Operators/index.html#//apple_ref/swift/opfunc/s:ZFSsoi2teuRq_Ss9Equatable_FTq_q__Sb

開発のプロが教える-Swift標準ガイドブック
http://www.amazon.co.jp/開発のプロが教える-Swift標準ガイドブック-渡辺-龍司/dp/4839953546

おわりに

Qiita初投稿でした!楽しかったです!

"プログラミングガイドを読むべし"みたいな話を何度か聞いたことがあったのですが、「参考書の方が速く読めるし、物によるけど説明も丁寧だし、、」と敬遠してきました。
今回初めてプログラミングガイドにしっかりと目を通し、「全部書いてある...。(当然)」と。
原典にあたる大切さを実感として得ることができました。

ビット演算子等まだ理解が及ばない部分も多いので、間違い等ありましたらご指摘下さい。

こういったイベントに積極的に参加する会社っていいですね!(宣伝)

KentaKudo
イギリスの会社でソフトウェアエンジニアをしています。
https://kentakudo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした