算術演算と初等関数
Julia には、すべての数値プリミティブ型に対して基本的な算術演算子とビット演算子を一通り揃えています。また、移植性の高い、効率的な実装の標準的な数学関数も揃えています。
算術演算子
次の 算術演算子は、すべてのプリミティブ数値型でサポートされています:
式 | 名前 | 説明 |
---|---|---|
+x | 単項加算 | 恒等演算 |
-x | 単項減算 | 加算の逆元への写像 |
x + y | 二項加算 | 加算を実行 |
x - y | 二項減算 | 減算を実行 |
x * y | 乗算 | 乗算を実行 |
x / y | 除算 | 除算を実行 |
x ÷ y | 整数除算 | x / y, 整数に切り捨て |
x \ y | 逆除算 | y / x と同等 |
x ^ y | 累乗 | x の y 乗 |
x % y | 剰余算 | rem(x,y) と同等 |
Bool
タイプの否定も同様です:
式 | 名前 | 説明 |
---|---|---|
!x | 否定 | true と false を逆にする |
A numeric literal placed directly before an identifier or parentheses, e.g. 2x
or 2(x+y)
, is treated as a multiplication, except with higher precedence than other binary operations. See Numeric Literal Coefficients for details.
Julia の昇格システムは、異なる型の引数型が混在した算術演算を自然かつ自動的うまく動作させます。昇格システムの詳細については、変換と昇格を参照してください。
算術演算子を使用した簡単な例を次に示します:
julia> 1 + 2 + 3
6
julia> 1 - 2
-1
julia> 3*2/12
0.5
(慣習的に周りの他の演算子より先に演算を行う演算では空白を詰めることがよくあります。たとえば、-x + 2
と書くのは、最初の x
に-1をかけてから2
を足すことを反映しています。)
ビット演算子
次の ビット演算子は、すべてのプリミティブ整数型でサポートされています:
式 | 名前 |
---|---|
~x | 否定(not) |
x & y | 論理積(and) |
x | y | 論理和(or) |
x ⊻ y | 排他的論理和(xor) |
x >>> y | 右論理シフト |
x >> y | 右算術シフト |
x << y | 左 論理/算術シフト |
ビット演算子を使用例を下記の通りです:
julia> ~123
-124
julia> 123 & 234
106
julia> 123 | 234
251
julia> 123 ⊻ 234
145
julia> xor(123, 234)
145
julia> ~UInt32(123)
0xffffff84
julia> ~UInt8(123)
0x84
代入演算子
すべての二項演算子・ビット演算子では、操作の結果を左の演算子に代入するバージョンの演算子が存在します。二項演算子の代入バージョンは、元の演算子の直後に =
をつけます。たとえば、x += 3
はx = x + 3
を書くのと同じです:
julia> x = 1
1
julia> x += 3
4
julia> x
4
すべての二項算術演算子とビット演算子の代入バージョンは以下のとおりです:
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=
代入演算子は、左辺側変数に再バインドを行います。結果、変数の方が変わることもあります。
julia> x = 0x01; typeof(x)
UInt8
julia> x *= 2 # Same as x = x * 2
2
julia> typeof(x)
Int64
ベクトル化した"ドット"演算子
全ての ^
のような二項演算子には、配列の各要素に対して ^
を実行するドット演算子 .^
が自動的に定義されます。たとえば、[1,2,3] ^ 3
は定義されていません。非正方の配列の3乗は数学的に意味を成さないからです。しかし、[1,2,3] .^ 3
は要素毎の計算として定義され、その結果は[1^3,2^3, 3^3]
となります。同様に、!
や √
のような単項演算子の場合も、演算子を要素的に適用する対応する .√
があります。
julia> [1,2,3] .^ 3
3-element Array{Int64,1}:
1
8
27
具体的には、a.^ b
は"ドット"呼び出し(^).(a,b)
として解析されます。これは、ブロードキャスト 操作を実行します: 配列とスカラー、同一サイズの配列2つ(要素ごとの演算子適用)そして、異なるサイズの配列(例えば、行ベクトルと列ベクトルの積)でさえも組み合わせ利用できます。さらに、すべてのベクトル化された"ドットコール"と同様に、これらの「ドット演算子」は融合的です。たとえば、配列A
に対して 2 .* A.^2 .+ sin(A)
(もしくは、@
マクロを使用して@. 2A^2 + sin(A)
とも書けますが)を計算する時、A
の要素に関するループを1回実行し2a^2 + sin(a)
を各要素に対して計算します。特に、f.(g.(x))
のような入れ子になったドットコールは融合され、x.+ 3 .* x.^2
のような "隣接する" 二項演算子は入れ子になったドットコール (+) .(x, (*).(3,(^).(x, 2)))
と等価になります。
さらに、a.+= b
(または @. a += b
) のような "ドットのついた" 代入演算子は a= a .+ b
として解析され、.=
は融合された インプレース 代入となります (ドット構文ドキュメントを参照してください)。
ドット構文は、ユーザーが定義した演算子にも適用できます。 たとえば、クローネッカー積(kron
)に便利なイン二項演算構文 A ⊗ B
を使うために⊗(A,B) = kron(A,B)
を定義した場合 、[A,B] .⊗[C,D]
は追加のコーディングなしで [A⊗B, B⊗D]
を計算します。
ドット演算子と数値リテラルの組み合わせがあいまいになる場合があります。 たとえば、1.+x
が 1. +x
と 1 .+ x
のどちらを意味するかは自明ではありません。したがって、この構文は許可されず、このような場合は演算子の周囲にスペースを使用する必要があります。
数値比較
すべてのプリミティブ数値型に対して標準的な比較演算子が定義されています:
演算子 | 名前 |
---|---|
== | 等号 |
!= , ≠ | inequality |
< | 未満 |
<= , ≤ | 以下 |
> | より大きい |
>= , ≥ | 以上 |
簡単な例を次に示します:
julia> 1 == 1
true
julia> 1 == 2
false
julia> 1 != 2
true
julia> 1 == 1.0
true
julia> 1 < 2
true
julia> 1.0 > 3
false
julia> 1 >= 1.0
true
julia> -1 <= 1
true
julia> -1 <= -1
true
julia> -1 <= -2
false
julia> 3 < -0.5
false
整数は、標準的なビットの比較の方法で比較されます。浮動小数点数はIEEE 754標準に従って比較されます:
- 有限数は通常の方法で順序付けされます。
- 正のゼロは負のゼロと等しく、負のゼロより大きくはない。
Inf
はそれ自体と等しく、NaN
を除く他のすべてよりも大きい。-Inf
はそれ自体に等しく、NaN
を除く他のすべての数より小さい。- 「NaN」は、それ自体を含め、何とも等しくなく、大きくも小さくもない。
最後のポイントは、ひょっとすると驚くべきことであり、したがって注目に値します:
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false
また、配列 と一緒に使うときには、頭痛の種になりえます:
julia> [1 NaN] == [1 NaN]
false
Julia では、特殊な値を検査する補助的な関数が提供されており、ハッシュ キーの比較などで役立ちます:
関数 | 検査内容 |
---|---|
isequal(x, y) | x と y が等しいか |
isfinite(x) | x は有限であるか |
isinf(x) | x は無限大であるか |
isnan(x) | x is NaNであるか |
isequal
は NaN
を互いに等しいと見なします:
julia> isequal(NaN, NaN)
true
julia> isequal([1 NaN], [1 NaN])
true
julia> isequal(NaN, NaN32)
true
isequal
は、符号付きゼロを区別するためにも使用できます:
julia> -0.0 == 0.0
true
julia> isequal(-0.0, 0.0)
false
符号付き整数、符号なし整数、および浮動小数点数が混在する比較は、難しい場合があります。Julia が正しい比較を行うために、多くの注意が払われてきました。
他の型については、isequal
はデフォルトで ==
を呼び出すので、独自の型の等価性を定義する場合は、==
メソッドを追加するだけで済みます。 さらに、isequal(x,y)
が True
となる時に hash(x) == hash(y)
でもあることを保証したいのであれば、対応する hash
メソッドも定義しなければいけないでしょう。
比較の連鎖
ほとんどの言語とは異なり、Julia は比較を任意に連鎖させることができます。(ほとんどの言語と言いましたが、なんとPythonは比較の連鎖ができます。)
julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true
比較の連鎖は数値計算のコードで大変便利に使えることが多いです。比較の連鎖では、スカラー比較には &&
演算子を使い、配列に対する要素毎の比較には &
演算子を使います。たとえば、0 .<A.<1
は、配列A
の要素で0 と 1 の間にある要素に対応する位置の要素がtrueであるような真偽値の配列を返します。
比較連鎖の振る舞いに注意してください:
julia> v(x) = (println(x); x)
v (generic function with 1 method)
julia> v(1) < v(2) <= v(3)
2
1
3
true
julia> v(1) > v(2) <= v(3)
2
1
false
真ん中の式は、v(1) < v(2) && v(2) <= v(3)
と書かれてた場合のように2回評価されるのではなく、1回だけ評価されています。ただし、比較連鎖の中での評価の順序は未定義です。(printなどの)副作用のある表現を使用しないことを強くお勧めします。もし副作用が必要な場合は、短絡演算子 &&
を明示的に使用する必要があります(参照: 短絡評価)。
初等関数
Juliaは一通りの数学関数と算術演算を提供します。これらの算術演算は、その意味をなす限り、整数、浮動小数点数、有理数、複素数など様々な数値クラスに対して定義されています。
さらに、これらの関数は(他のJulia関数と同様に)、「ベクトル化」した形で配列やその他のコレクションに対して適用することができます。その際には、dot構文
f.(A)
を使い、例えば sin.(A)
は配列A
の各要素に対してsinの値を適用します。
演算子の優先順位と結合則
Julia では、下記の優先順位と結合則で、上から下へと演算子が適用されます:
種別 | 演算子 | 結合則 |
---|---|---|
構文 | まずは. 次に :: | 左 |
累乗 | ^ | 右 |
単項演算子 | + - √ | 右[1] |
シフト | << >> >>> | 左 |
分数 | // | 左 |
乗算 | * / % & \ ÷ | 左[2] |
加算 | + - | ⊻ | 左[2] |
構文 | : .. | 左 |
構文 | |> | 左 |
構文 | <| | 右 |
比較 | > < >= <= == === != !== <: | 非結合 |
制御 | まずは && その次に || そして ? | 右 |
対 | => | 右 |
代入 | = += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>= | 右 |
単項演算子 +
と -
には、明示的に括弧をつけて、++
などの演算子との曖昧性を排除する必要があります。他の単項演算子の結合は右結合として解析される。例えば、√√-a
は √(√(-a))
と解釈されます。.
演算子 +
, ++
, *
は、非結合的です。つまり a + b + c
は +(+(a, b),c)
ではなく、+(a, b, c)
と解析されます。ただし、 フォールバックメソッドの+(a, b, c, d...)
や *(a, b, c, d...)
はどちらもデフォルトでは左結合で評価されます。
Julia における 全ての 演算子の優先順位の完全なリストは、このファイルの上部を参照してください: src/julia-parser.scm
Numeric literal coefficients, e.g. 2x
, are treated as multiplications with higher precedence than any other binary operation, and also have higher precedence than ^
.
また、組み込み関数 Base.operator_precedence
を使用して、特定の演算子の数値の優先順位をつきとめることもできます:
julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)
(11, 13, 17)
julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`)
(0, 1, 1)
演算子を表すシンボルの結合則も組み込み関数 Base.operator_associaivity
を呼び出すことによっても見つけることができます:
julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)
(:left, :none, :right)
julia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)
(:left, :none, :right)
:sin
などのシンボルは 0
を返します。この値は引数に与えられたシンボルが演算子として無効であることを表しているだけで、優先順位が最も低いということではありません。同様に、このような演算子には結合性は :none
が割り当てられます。
数値変換
Julia は、3 つの形式の数値変換をサポートしていますが、これらはそれぞれ厳密な変換ができないときの扱いが異なります。
T(x)
またはconvert(T,x)
はx
を型T
の値に変換します。T
が浮動小数点型の場合、結果は最も近い表現可能な値であり、正または負の無限大になる可能性があります。T
が整数型の場合,x
がT
で表せない場合にはInexactError
が発生します。.
x % T
はx
を整数型T
の、2^n
を法として、x
と合同な数に変換します。ここでn
はT
のビット数です。言い換えると、2進数表現をT
で表現できるよう切り捨てをしています。丸め関数 はオプションの引数として、型
T
をとります。例えば,round(Int,x)
はInt(round(x))
の略記です。
以下にそれぞれの例を示します。
julia> Int8(127)
127
julia> Int8(128)
ERROR: InexactError: trunc(Int8, 128)
Stacktrace:
[...]
julia> Int8(127.0)
127
julia> Int8(3.14)
ERROR: InexactError: Int8(3.14)
Stacktrace:
[...]
julia> Int8(128.0)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]
julia> 127 % Int8
127
julia> 128 % Int8
-128
julia> round(Int8,127.4)
127
julia> round(Int8,127.6)
ERROR: InexactError: trunc(Int8, 128.0)
Stacktrace:
[...]
独自の変換と昇格を定義する方法については、変換と昇格を参照してください。
丸め関数
関数 | 説明 | 戻り値の型 |
---|---|---|
round(x) | x を最も近い整数に丸める | typeof(x) |
round(T, x) | x を最も近い整数に丸める | T |
floor(x) | x を-Inf の方向に丸める | typeof(x) |
floor(T, x) | x を-Inf の方向に丸める | T |
ceil(x) | x を +Inf の方向に丸める | typeof(x) |
ceil(T, x) | x を+Inf の方向に丸める | T |
trunc(x) | x を ゼロの方向に丸める | typeof(x) |
trunc(T, x) | x をゼロの方向に丸める | T |
除算関数
関数 | 説明 |
---|---|
div(x,y) , x÷y | 切り落とし除算; ゼロ方向に丸めた商 |
fld(x,y) | floor除算; -Inf 方向に丸めた商 |
cld(x,y) | ceil除算; +Inf 方向に丸めた商 |
rem(x,y) | 剰余(remainder); x == div(x,y)*y + rem(x,y) ; 符号は x と一致 |
mod(x,y) | 剰余(modulus); x == fld(x,y)*y + mod(x,y) ; 符号は y と一致 |
mod1(x,y) | 1オフセットをしたmod ; mod(r, y) == mod(x, y) を満たし y>0 の場合 r∈(0,y] 、y<0 の場合 r∈[y,0) となるような r を返す |
mod2pi(x) | 2pi を法とする剰余; 0 <= mod2pi(x) < 2pi |
divrem(x,y) | (div(x,y),rem(x,y)) を返す |
fldmod(x,y) | (fld(x,y),mod(x,y)) を返す |
gcd(x,y...) | x , y ,... の正の最大公約数 (greatest positive common divisor) |
lcm(x,y...) | x , y ,... の正の最小公倍数 (least positive common multiple) |
符号関数と絶対値関数
関数 | 説明 |
---|---|
abs(x) | x の絶対値 |
abs2(x) | x の絶対値の二乗 |
sign(x) | x の符号。 returning -1, 0, +1 のいずれかを返す |
signbit(x) | サインビットが立っているかどうか true/false を返す |
copysign(x,y) | sign(y) * abs(x) を返す |
flipsign(x,y) | sign(x*y) * abs(x) を返す |
累乗・対数・平方根
関数 | 説明 |
---|---|
sqrt(x) , √x | x の平方根 |
cbrt(x) , ∛x | x の三乗根 |
hypot(x,y) | 直角を挟む2辺の長さがx , y である直角三角形の斜辺の長さ |
exp(x) | 自然指数関数 の x での値 |
expm1(x) | ゼロ近傍のx に対する exp(x)-1 の正確な値を返す |
ldexp(x,n) | 整数値 n に対する x*2^n を効率的に計算する |
log(x) | 自然対数の x での値 |
log(b,x) | 底b の対数のx での値 |
log2(x) | 底2 の対数のx での値 |
log10(x) | 底10の対数のx での値 |
log1p(x) | ゼロ近傍のx に対する log(1+x) の正確な値 |
exponent(x) | 浮動小数点x の 2を基数とする指数部分 |
significand(x) | 浮動小数点 x の 2を基数とする仮数部分 |
hypot
、expm1
、およびlog1p
のような関数が必要かつ有用である理由概説については、John D. Cook の優れたブログ投稿を参照してください: expm1, log1p,erfc、および hypot。
三角関数と双曲線関数
すべての標準的な三角関数と双曲線関数も定義されています:
sin cos tan cot sec csc
sinh cosh tanh coth sech csch
asin acos atan acot asec acsc
asinh acosh atanh acoth asech acsch
sinc cosc
これらはすべて単一引数関数ですが、atan
は2つの引数をとることもでき、そのときは 従来のatan2
関数の振る舞いになります。
また、sinpi(x)
とcospi(x)
は、それぞれsin(pi*x)
とcos(pi*x)
のより正確な計算のために提供されます。
ラジアンの代わりに"度"を使用して三角関数を計算するには、関数の接尾辞を d
で囲みます。たとえば、sind(x)
はx
が"度"で指定されるx
のsinを計算します。 "度"を入力に使用した三角関数の完全なリストは次のとおりです:
sind cosd tand cotd secd cscd
asind acosd atand acotd asecd acscd
特殊関数
他の多くの特殊関数は、パッケージSpecialFunctions.jlで提供されています。