Julia - 演算子
Julia の特徴的な演算子機能としては、べき乗と逆除算が用意されていること、そして言語機能のレベルで演算子のベクトル化が可能であることが挙げられる。C/C++ や Java などの言語知識があれば多くは読み飛ばしてもかまわない。
算術演算子
表現 | 名前 | 動作 |
---|---|---|
+ \(x\) |
単項プラス | 値をその値自身に変換する (無操作) |
- \(x\) |
単項マイナス | 値をその反数に変換する |
\(x\)+ \(y\) |
加算 | 加算を行う |
\(x\)- \(y\) |
減算 | 減算を行う |
\(x\)* \(y\) |
乗算 | 乗算を行う |
\(x\)/ \(y\) |
除算 | 除算を行う |
\(x\)\ \(y\) |
逆除算 | \(y / x\) と等価 |
\(x\)^ \(y\) |
べき乗 | \(x^y\) を計算 |
\(x\)% \(y\) |
余剰 | 余剰を計算; rem(x,y) と等価 |
! \(x\) |
否定 | \(x\) がブール代数のとき true と false を逆転させる |
Julia では一般的な言語の算術演算子に加えて逆除算とべき乗が定義されている。また特徴的な構文解釈として定数×変数であれば乗算演算子を省略することができる。
(2*pi)^0.5 # => 2.5066282746310002
(2*pi)^0.5 \ 1 # => 0.3989422804014327
1 / (2*pi)^0.5 # => 0.3989422804014327
x=2; 2x+1 # => 5
比較演算子
表現 | 名前 |
---|---|
== |
等価 |
!= , ≠ |
非等価 |
< |
未満 |
<= , ≤ |
以下 |
> |
より大きい |
>= |
以上 |
比較演算子は一般的な言語で使用されている通り。≠, ≤ のような非 ASCII 記号も使用されている。
論理演算子
表現 | 名前 |
---|---|
&& |
論理積 (短絡評価) |
|| |
論理和 (短絡評価) |
& |
論理積 |
| |
論理和 |
短絡評価 (ショートサーキット) は左オペランドを評価した時点で結果が確定されれば右オペランドは評価されないというもの。処理の効率化のために一般的な言語で用いられているものと同じ。
julia> a = 10
julia> a < 10 && (println("right"); true)
false
julia> a < 10 & (println("right"); true)
right
false
シェルや LL 言語と同様に Julia の短絡評価も簡易的な条件文として使用することができる。ただし右オペランドも Bool 型の必要がある。
! isinf(y) || error("arithmetical overflow!")
(save_a() & save_b() & save_c()) || error("one or more saving failed!")
代入演算子
表現 | 名前 |
---|---|
= |
代入 |
+= |
算術加算代入 |
-= |
算術減算代入 |
*= |
算術乗算代入 |
/= , ÷= |
算術除算代入 |
\= |
算術逆除算代入 |
%= |
算術余剰代入 |
^= |
算術べき乗代入 |
&= |
ビット論理積代入 |
|= |
ビット論理和代入 |
⊻= |
ビットXOR代入 |
>>>= |
ビット右シフト代入 |
>>= |
ビット右シフト代入 |
<<= |
ビット左シフト代入 |
左オペランド (左辺値) と右オペランドを演算した結果を左オペランドに代入する操作付き代入が定義している。これは C や Java では一般的な機能。
ビット演算子
表現 | 名前 |
---|---|
~ \(x\) |
ビット否定 |
\(x\)& \(y\) |
ビット論理積 |
\(x\)| \(y\) |
ビット論理和 |
\(x\)⊻ \(y\) |
ビットXOR (排他OR) |
\(x\)>>> \(y\) |
ビット右シフト |
\(x\)>> \(y\) |
ビット右シフト (符号ビットを維持) |
\(x\)<< \(y\) |
ビット左シフト |
ビット操作のために2進数、8進数、16進数リテラルを使用するとき、10進数リテラルと違って幅が自動調整されることに注意。
a = 0b110010
b = 0b100110
typeof(a) # => UInt8
bin(~a) # => "11001101"
bin(a & b) # => "100010"
bin(a | b) # => "110110"
bin(a ⊻ b) # => "10100"
右シフト演算 >>
は左オペランド (左辺値) が符号付き整数 IntNN の場合、かつ、負の値の場合に、右シフト操作後の最上位ビットを 1 で埋める。これは負値に対しても2のべき乗で整数除算した結果となるため \(\lfloor\frac{x}{2^y}\rfloor\), \(y=0,1,\ldots\) を高速に計算する目的で右シフトを使用するときに有用である。
>>>
は左オペランドが符号付き整数であっても UInt とおなじように右シフトを行い最上位ビットを 0 で埋める。整数を純粋なビットの並びとして扱っているのであればこちらを使うとよい。
左オペランドが UInt の場合、2種類の右シフト演算子はどちらも同じ結果となる。
a = Int8(-10)
typeof(a) # => Int8
bin(a & 0xFF, 8) # => "11110110"
a >> 2 # => -3
bin((a >> 2) & 0xFF, 8) # => "11111101"
a >>> 2 # => 61
bin((a >>> 2) & 0xFF, 8) # => "00111101"
bin(0b1010 << 4, 8) # => "10100000"
0b1010 << 4 # => 0xa0
演算子のベクトル化
Julia は演算子や関数の前後にドット .
を付けることでベクトルや行列のすべての要素に対しての演算操作を行うことができる。これは NumPy のブロードキャストと同様に記述の簡略化と併せてベクトル演算ユニットを利用することを目的としていて、実行環境が GPU を利用可能であれば大規模な行列を高速に演算処理することができる。
julia> a = rand(2, 3)
2×3 Array{Float64,2}:
0.158746 0.448244 0.434901
0.660539 0.216962 0.718644
julia> a .* 2
2×3 Array{Float64,2}:
0.317492 0.896487 0.869802
1.32108 0.433925 1.43729
julia> (a .* 2) .^ 2
2×3 Array{Float64,2}:
0.100801 0.80369 0.756555
1.74525 0.188291 2.0658
julia> sqrt.(a)
2×3 Array{Float64,2}:
0.398429 0.66951 0.65947
0.812735 0.465792 0.847729