LoginSignup
5
4

More than 3 years have passed since last update.

Julia その1

Last updated at Posted at 2019-05-07

Juliaという言語がある。Amazon.co.jpでぐぐると18禁ページにとばされそうになってびっくりする。

JuliaboxというサイトでJupyter ノートブックで使える。言語としてはRubyとかPythonとかのようなスクリプト言語のように見えるが実はなかなかハードコアで、動的に特定の型に特化されたバージョンがJITでコンパイルされて動作するのでかなり速い、らしい。

結構特徴的な言語仕様なので、面白いところを紹介する。

1オリジン

Juliaはコンピュータサイエンティスト向けというよりは数学者向けの言語で、その証拠に、配列の添字が1で始まる。配列の添字が1で始まる言語はRとかその前身のSとか、古のFortranとか、APLとか、数学者向けなのだ。コンピュータ屋にとっては配列のインデックスはベースアドレスに足す数なので、1オリジンとか気が狂ってるように見えるのだけど、数学者にとっては「0番目の要素」とか言われるとやっぱり気が狂っているように見えるのだろう。

> a = [1,2,3]
> a[1]  
1

これがPythonだと当然下のようになる。なれるまでは時間かかりそう。

> a = [1, 2, 3]
> a[1]
2

ans

REPLの中ではansという変数が特殊な変数扱いになっていて、直前の入力の評価結果になる。

julia> 1+1
2
julia> ans
2

スクリプトとして使うときには当然使えない。

係数の書き方

数学だと2xと書くと2かけるxという意味になり、係数が省略できるが、一般のプログラミング言語では、2 * xのように掛け算であることを明示する必要がある。ところがJuliaでは2xのように直接書くことができる。スペースを開けるとエラーになる。数字で始まる変数名は許されないのでパーズできるのだろう。変数名がeとかだと指数表記との区別が結構面倒なコーナーケースがありそうだけど問題ないのだろうか。

試してみたら案の定、結構面倒。

> x = 2
> 2x+1
5  # 2 * 2 + 1

だが、

> e = 2
> 2e+1
20 #  2 * 10 ^ 1

となる。。。数値の後にe+ もしくはe-がくるとパースを変えるようだ。割にアドホック。
変数名としてeを使ってはいけない、ということだな。

変数名

任意のユニコード文字が変数として使える。それは今どきの言語としては別に珍しくもないが、JuliaのREPLにはlatexライクなギリシャ文字変換機能がついているので、かな漢字変換の無い環境のユーザにも使いやすくなっている。例えばπであれば\piとうってからtab でπに変換される。

ちなみにπには円周率(の近似値)がはじめから入っている。便利だ。

julia> π
π = 3.1415926535897...
julia> sin(0.5π)
1.0

変数名は些細な話のようにも思えるけど、数式を引き写すときにはかなり便利っぽい。μとかσとかをそのまま使えるのはよい。。

REPLで変換できる文字のリストがここにある。恐ろしい数が定義されているけど、区別がつかないものも多数。。

有理数

分子と分母の2つの整数で表す有理数もサポートされている。
python の fractions と同じような機能だが、言語で直接サポートされているので、ずっと書きやすい。//で区切って書く。

julia> 1//3 * 3
1//1

有理数と浮動小数点を足すと浮動小数点になる。

Julia> 1//3 * 3.0
1.0

有理数と整数の演算は、有理数のまま。

julia> 1//3 * 3
1//1

分子部分を取り出すにはnumerator、分母部分を取り出すにはdenominatorを用いる。

julia> numerator(2//3)
2
julia> denominator(2//3)
3

複素数

Juliaは複素数をネイティブでサポートしている。算術演算系の演算子も複素数をサポートしている。すごい。リテラルとしては虚数単位を予約変数imで書く。

julia> typeof(1 + 1im)
Complex{Int64}
julia> typeof(1 + 1.0im)
Complex{Float64}

算術演算子が複素数をサポートしているので、例えばオイラーの公式の左辺をこんなふうに書くことができる。 eではなくて、自然対数の底を表すいわゆるネイピア数で、π同様もともと定義されている。REPLからだと\euler + tab で出すことができる。

julia> f(θ) = ℯ^(im * θ)
f (generic function with 1 method)
julia> f(π)
-1.0 + 1.2246467991473532e-16im

うーん素晴らしい。
ちょっと面白いのはsqrtの挙動。sqrt(-1)は実数の範囲には解がないので、エラーが出る。でも、複素数なら解があるのでちゃんと動く

julia> sqrt(-1.0)
ERROR: DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31
 [2] sqrt(::Float64) at ./math.jl:492
 [3] top-level scope at none:0

julia> sqrt(-1.0 + 0.0im)
0.0 + 1.0im

リテラルとしてではなく複素数を作るにはcomplex関数を用いる。実部、虚部を取り出すにはそれぞれrealimagを、共役数を得るにはconjを用いる。angleは実軸からの回転角を返す。

julia> c = complex(1.0 + 1.0im)
1.0 + 1.0im
julia> real(c)
1.0
julia> imag(c)
1.0
julia> conj(c)
1.0 - 1.0im
julia> angle(c)
0.7853981633974483

割り算系演算子

ちなみに、Python3では//は商の整数の部分を表す。整数同士の割り算が浮動小数点を返すという仕様のせい。

>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3

実はJuliaも同じように、整数の割り算結果が浮動小数点で返される。では//に当たる演算子はどうなっているのかというと、なんと÷を使う。これは\div + tabで出せる。

julia> 10 / 3
3.3333333333333335
julia> 10 ÷ 3
3
julia> 10 % 3
1

このように普通のキーボードで直接打てない演算子は他にもいくつかあるようだ。昔あったAPLはおかしな記号だらけだったけど、それに近いものを感じる。。しかし、REPLではlatex記法で打てるにしても、エディタでプログラムを書く場合にはどうやって出すんだろうか。われわれ日本人はIMEでなんとかなるが。

さらに!\という演算子も定義されている。a \ bb / aと等価。これいるかなあ。。

julia> 10 \ 3
0.3
5
4
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
5
4